C++14使用std::make_shared传递constexpr静态成员出现未定义引用问题
问题场景
使用-std=c++14标准编译如下代码:
#include <memory> class A { public: static constexpr int c = 0; std::shared_ptr<int> b; A() { b = std::make_shared<int> (c); } }; int main () { A a; return 0; }
会报链接错误:undefined reference to 'A::c'。
如下修改代码后即可正常编译运行:
class A { public: static constexpr int c = 0; std::shared_ptr<int> b; A() { int cc = c; b = std::make_shared<int> (cc); } };
原因解释
C++14及更早标准中,类内完成初始化的static constexpr成员,只有在不触发*odr使用(单定义规则使用)*的场景下才不需要额外类外定义:
- 出错场景中,
std::make_shared<int>的参数是const T&类型,传递A::c的时候会触发odr使用,要求A::c必须有实际的内存地址,也就是必须在类外补充定义,否则链接阶段找不到符号就会报错。 - 正常场景中,
int cc = c;属于编译期常量取值,编译器会直接把c的值0替换到赋值语句中,不需要c的内存地址,不会触发odr使用,因此不需要额外定义就能正常编译。
修复方法
- 方法1:保留C++14编译标准的情况下,在类定义的外部补充
A::c的定义:
constexpr int A::c;
- 方法2:升级编译标准到C17及以上,C17开始类内初始化的
static constexpr成员默认是inline的,不需要额外类外定义,无论是否被odr使用都能正常编译链接。
内容的提问来源于stack exchange,提问作者Nicola Lissandrini
相关产品推荐
相关产品推荐

