C++中constexpr static数据成员是否始终需要在类外定义?
C++ constexpr static 数据成员定义规则变更说明
1. 规则差异本质是C++标准变更导致的
- C11、C14标准中,类内初始化的
constexpr static数据成员仅属于声明,不属于完整定义。如果该成员被odr-use(单一定义规则使用),例如示例中作为引用参数传递、对其取地址等需要访问内存地址的场景,就必须在类外额外提供一个全局的定义,否则会出现链接阶段未定义引用的错误。 - C++17标准新增了*内联变量(inline variable)*特性,同时明确规定:类内完成初始化的
constexpr static数据成员会隐式声明为inline,此时类内的声明同时就是完整定义,不需要再额外在类外补充定义,代码可以直接编译链接通过。
2. 是否需要始终保留类外定义
你可以根据项目的兼容需求选择:
- 如果你的项目需要兼容C++14及更早的标准,必须保留类外定义,避免odr-use场景下的链接错误
- 如果你的项目仅需要支持C++17及更高版本,完全可以删除类外的冗余定义,不会产生任何问题
- 如果你开发的是需要跨多版本标准兼容的公共库,保留类外定义也不会出错,C++17及更高版本允许这种冗余的类外定义,不会触发重定义错误
参考代码示例
struct Array{ int static constexpr sz_ = 5; int ar_[sz_]{}; }; // C++11、C++14下odr-use sz_时必须打开下行注释,C++17及以后不需要 //int constexpr Array::sz_; void foo(int const& x){ } int main(){ foo(Array::sz_); // 此处属于odr-use sz_,需要该成员有完整定义 }
内容的提问来源于stack exchange,提问作者Itachi Uchiwa
相关产品推荐
相关产品推荐

