shared_ptr 中对 const int 的未定义引用

undefined reference to const int within shared_ptr

我有配置class

// config.hpp

class Config {
  public:
    static constexpr int a = 1;
    static constexpr int b = 1;
}

并包含在 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
}

编译器说 undefined reference to Config::a

并且在使用 cout 时有效,但在 shared_ptr 构造函数中无效。

我不知道为什么会这样。

请注意 std::make_shared takes parameter by reference, which causes Config::a to be odr-used 因为它将绑定到引用参数,所以它在命名空间范围内的定义是必需的(在 C++17 之前)。

另一方面,std::cout << Config::a不会导致Config::a被odr使用,因为std::basic_ostream::operator<< (int)按值获取参数,Config::a则受制于请求左值到右值的转换以复制初始化参数,因此 Config::a 未使用 odr。

如果一个对象被 odr 使用,它的定义必须存在。您可以将定义(在实现文件中)添加为

constexpr int Config::a; // only necessary before C++17

注意它不能有初始化器。

LIVE

由于 C++17 constexpr static data member 是隐式内联的,因此不再需要此类定义,因此您的代码在 C++17 中运行良好。

If a static data member is declared constexpr, it is implicitly inline and does not need to be redeclared at namespace scope. This redeclaration without an initializer (formerly required as shown above) is still permitted, but is deprecated.

LIVE

你的 a 是私有的,或者 public: 需要在它之前,或者使 class 成为一个结构以获得默认值 public。但这在 C++14 下编译 https://godbolt.org/g/tS4M1Z

#include <iostream>
#include <memory>

struct Config {
  static constexpr int a = 1;
  static constexpr int b = 1;
};

struct otherClass {
    otherClass( int c ) { }
};

int main () {
  std::cout << Config::a << std::endl; // this is ok
  std::shared_ptr<otherClass> stream = std::make_shared<otherClass>( Config::a ); // compile error
}