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

2022-01-23 00:00:00 static constants c++ member

假设我有一个需要一些常量才能运行的类.几个成员函数需要使用这些常量.不赞成使用#define,因为它会导致冲突.常量是 8 位或 16 位的十六进制模式,存储为 uint8_t 或 uint16_t.这些常量也不会因类的实例而异,因此只需保存一份常量副本即可节省内存(尽管内存很少).

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.

有什么不合适的,或者可能是更好的方法来完成上述操作,而不是简单地执行以下操作:

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;
// .......
};

提前感谢您的帮助.

推荐答案

鉴于您对情况的描述,我想说使用 static const 成员是一个好方法.在 C++11 中,您可能希望将其更改为 static constexpr 以强调它是编译时常量,尽管不会因此而有效地改变.

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

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

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:

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

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

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

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

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

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

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.

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

A final comment on the data type: Forcing it into 16 bits using std::uint16_t can 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.

相关文章