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
注意它不能有初始化器。
由于 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.
你的 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
}
我有配置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
注意它不能有初始化器。
由于 C++17 constexpr
static data member 是隐式内联的,因此不再需要此类定义,因此您的代码在 C++17 中运行良好。
If a
static
data member is declaredconstexpr
, it is implicitlyinline
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.
你的 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
}