C++ 静态常量成员变量用法

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17056882/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 20:53:14  来源:igfitidea点击:

C++ Static Const Member Variable Usage

c++staticconstmember

提问by It'sPete

Say that I have a class that requires a few constants to function. Several member functions require use of these constants. Use of #define is frowned upon since it can cause collisions. The constants are hex patterns of 8 or 16 bits and are stored as uint8_t or uint16_t. These constants also don't change from instance to instance of the class, and therefore memory (albeit very little memory) can be saved by having only one copy of the constants.

假设我有一个需要一些常量才能起作用的类。几个成员函数需要使用这些常量。不赞成使用#define,因为它会导致冲突。常量是 8 位或 16 位的十六进制模式,并存储为 uint8_t 或 uint16_t。这些常量也不会在类的实例之间发生变化,因此可以通过只有一个常量副本来节省内存(尽管内存非常少)。

Is there anything improper, or perhaps of better way of accomplishing the above instead of simply doing something like the following:

是否有任何不当之处,或者可能有更好的方法来完成上述操作,而不是简单地执行以下操作:

// mycode.h
// .......
class myclass {
private:
  static const uint16_t kMyClassConstant_ = 0xBEEF;
// .......
};

Thanks in advance for the help.

在此先感谢您的帮助。

回答by jogojapan

Given your description of the situation, I'd say using static constmembers is a good approach. In C++11 you may want to change it into static constexprto emphasize it's a compile-time constant, although nothing will effectively change as a result of that.

鉴于您对情况的描述,我认为使用static const成员是一种好方法。在 C++11 中,您可能希望将其更改为static constexpr强调它是编译时常量,尽管因此不会有效地更改任何内容。

If you refer to myclass::kMyClassContant_somewhere in the code in a way that is relevant under the one-definition-rule (odr), esp. in contexts that require a reference (including const-reference), the compiler will complain that there is no definition of the constant. Merely declaring and initializing it inside the class isn't sufficient in this case. This may force you to separate declaration and definition:

如果您以myclass::kMyClassContant_一种与单一定义规则 (odr) 相关的方式引用代码中的某处,尤其是。在需要引用(包括常量引用)的上下文中,编译器会抱怨没有常量的定义。在这种情况下,仅仅在类中声明和初始化它是不够的。这可能会迫使您将声明和定义分开:

// mycode.h
class myclass {
private:
  static const uint16_t kMyClassConstant_;
};

// mycode.cpp
const uint16_t myclass::kMyClassConstant_ = 0xBEEF;

To avoid the trouble of maintaining separate declarations and definitions, some people prefer declaring an inline constexpr function instead of an actual variable:

为了避免维护单独声明和定义的麻烦,有些人更喜欢声明内联 constexpr 函数而不是实际变量:

// mycode.h
class myclass {
private:
  static constexpr uint16_t kMyClassConstant_()
  { return 0xBEEF; }
};

This is a correct work-around for many of the odr-related problems, and it does not cause any loss in performance. Whether it is really useful depends on how much of a burden it is to maintain separate declarations and definitions of an ordinary static constant. If you expect your constants to never change as your code evolves, using ordinary static constants with separate definitions is preferable. But if you modify the definitions of the constants frequently, having to re-compile the definition file and re-link it to all relevant parts of the project may make you consider the function-based solution above as a better alternative.

对于许多与 odr 相关的问题,这是一种正确的解决方法,并且不会导致任何性能损失。它是否真的有用取决于维护普通静态常量的单独声明和定义的负担有多大。如果您希望常量永远不会随着代码的发展而改变,那么最好使用具有单独定义的普通静态常量。但是,如果您经常修改常量的定义,则必须重新编译定义文件并将其重新链接到项目的所有相关部分,可能会使您认为上述基于函数的解决方案是更好的选择。

A final comment on the data type: Forcing it into 16 bits using std::uint16_tcan be useful if you need to store lots of these values in compact form. Otherwise, the actual size may not really matter, in which case std::uint_fast16_t(which may be larger than 16 bits) may be better.

关于数据类型的最后评论:std::uint16_t如果您需要以紧凑形式存储大量这些值,则使用强制将其转换为 16 位会很有用。否则,实际大小可能并不重要,在这种情况下std::uint_fast16_t(可能大于 16 位)可能会更好。

回答by Jan Herrmann

You could use type traits to implement this:

您可以使用类型特征来实现这一点:

#include <type_traits>

class myclass {
private:
  typedef std::integral_constant<uint16_t , 0xBEEF> kMyClassConstant;

  // ...
};

used as myclass::kMyClassConstant::value.

用作myclass::kMyClassConstant::value.

This shows the purpose of implementing an integral constant and prevents you from accidentaly taking an address of the constant.

这显示了实现整数常量的目的,并防止您意外获取常量的地址。

回答by Acorn

Since C++17, we have access to inlinevariables, which take care of the odr-related problems. Several options:

从 C++17 开始,我们可以访问inline变量,这些变量处理与 odr 相关的问题。几个选项:

// mycode.h
class myclass {
    static const inline uint16_t kMyClassConstant_ = 0xBEEF;
};

Or, if it can be marked constexpr(like in this case):

或者,如果它可以被标记constexpr(就像在这种情况下):

// mycode.h
class myclass {
    static constexpr inline uint16_t kMyClassConstant_ = 0xBEEF;
};

Which can be simplified to:

可以简化为:

// mycode.h
class myclass {
    static constexpr uint16_t kMyClassConstant_ = 0xBEEF;
};

Because in C++17 constexprimplies inlinefor staticdata members.

因为在C ++ 17constexpr意味着inline用于static数据成员。