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

It'*_*ete 27 c++ static const member

假设我有一个类需要一些常量来运行.几个成员函数需要使用这些常量.使用#define是不受欢迎的,因为它可能导致冲突.常量是8位或16位的十六进制模式,存储为uint8_t或uint16_t.这些常量也不会从类的实例更改为实例,因此只需要一个常量副本就可以保存内存(尽管内存非常少).

是否存在任何不正确的,或者更好的方式来实现上述内容,而不是简单地执行以下操作:

// mycode.h
// .......
class myclass {
private:
  static const uint16_t kMyClassConstant_ = 0xBEEF;
// .......
};
Run Code Online (Sandbox Code Playgroud)

在此先感谢您的帮助.

jog*_*pan 45

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

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

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

// mycode.cpp
const uint16_t myclass::kMyClassConstant_ = 0xBEEF;
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

  • 我一直在关注你的答案,据我所知,就澄清和精确而言,它们是最好的.这与一些具有高"声誉"的人形成鲜明对比,他们不断呼吁神秘化,而不是回答问题.祝贺(+1) (8认同)

Jan*_*ann 5

您可以使用类型特征来实现此目的:

#include <type_traits>

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

  // ...
};
Run Code Online (Sandbox Code Playgroud)

用作myclass::kMyClassConstant::value.

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


Aco*_*orn 5

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

// mycode.h
class myclass {
    static const inline uint16_t kMyClassConstant_ = 0xBEEF;
};
Run Code Online (Sandbox Code Playgroud)

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

// mycode.h
class myclass {
    static constexpr inline uint16_t kMyClassConstant_ = 0xBEEF;
};
Run Code Online (Sandbox Code Playgroud)

可以简化为:

// mycode.h
class myclass {
    static constexpr uint16_t kMyClassConstant_ = 0xBEEF;
};
Run Code Online (Sandbox Code Playgroud)

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