对shared_ptr中的const int的未定义引用

ale*_*.tu 5 c++ definition one-definition-rule constexpr c++17

我有一个Config课程

// config.hpp

class Config {
  public:
    static constexpr int a = 1;
    static constexpr int b = 1;
}
Run Code Online (Sandbox Code Playgroud)

并包含在main.cpp中

// main.cpp
#include "config.hpp"
int main () {
  std::cout << Config::a << std::endl; // this is ok
  std::shared_ptr<otherClass> stream = std::make_shared<otherClass>( 
Config::a); // compile error
}
Run Code Online (Sandbox Code Playgroud)

和编译器说 undefined reference to Config::a

它在使用时起作用cout,但在shared_ptr构造函数中不起作用.

我不知道为什么会这样.

son*_*yao 7

请注意,std :: make_shared通过引用获取参数,这会导致Config::a使用odr,因为它将绑定到引用参数,然后在命名空间范围内定义它是必需的(在C++ 17之前).

另一方面,std::cout << Config::a不会导致Config::a使用odr,因为std :: basic_ostream :: operator <<(int)按值获取参数,Config::a然后要求lvalue-to-rvalue转换请求copy-initialize参数因此Config::a,没有使用.

如果对象使用了odr,则其定义必须存在.您可以将定义(在实现文件中)添加为

constexpr int Config::a; // only necessary before C++17
Run Code Online (Sandbox Code Playgroud)

请注意,它不能有初始化程序.

生活

由于C++ 17 constexpr静态数据成员是隐式内联的,因此不再需要这样的定义,因此您的代码在C++ 17中运行良好.

如果static声明了数据成员constexpr,则它是隐式的inline,不需要在命名空间范围内重新声明.没有初始化程序(以前需要如上所示)的重新声明仍然允许,但已弃用.

生活