何时需要定义类的静态数据成员 (un/-)
When is definition of class' static data member (un/-)necesary
我有一个大项目,正在努力重构它。主要任务是重写记录器。新的记录器(据我所知(与旧记录器API兼容,所以我相信在更改标头包含目录后,重新编译并重新链接一切都应该可以工作。但是没有。我收到多个此类错误undefined reference to <static_data_member>
.我无法粘贴实际代码,但它看起来像这样:
// Foo.h
class Foo {
static const int bar = 0;
int baz; // assigned in c-tor
void updateBaz() { baz = bar; }
// ....
}
static const int bar
在 Foo.cpp 中没有定义。它有时由日志宏打印。它曾经工作(使用旧的记录器(,现在我必须定义它。是什么变化导致了它?
另一个例子发生在boost声明的变量中:
(...)/blog_adaptor.h:50: error: undefined reference to bbost::serialization::version<CA::CReyzinSignature>::value'
那么:什么时候需要静态成员的定义,什么时候可以省略它们?
除非变量被声明为inline
(C++17 特征(,否则就C++标准而言,静态成员变量的定义不是可选的。未能提供定义是未定义的行为。
编译器和链接器可能会有所不同,确切地说是什么使它们检查是否存在定义,但这是未定义行为的本质。
正如Nicol Bolas回答的那样,我的项目中的代码具有未定义的行为,因为静态数据成员已初始化,但没有定义。总结和扩展: 在以下情况下不需要定义静态数据成员:
- 它不使用或仅在丢弃的分支中使用(constexpr-if 的非实例化模板和丢弃的分支(
- 在 C++17 中,如果成员是内联的
- Clang-Tidy还说"constexpr静态数据成员的离线定义在C++17中是多余的,并且已被弃用",所以可能静态constexpr也不需要它
此外,以下代码显示了为什么我的错误项目之前没有触发链接器错误。我不知道是"不是odr使用"还是"尚未伤害您的未定义行为":
#include <boost/serialization/version.hpp>
class Klass {};
//BOOST_CLASS_VERSION(Klass, 3);
// would be expanded to:
namespace boost { namespace serialization {
template<>
struct version<Klass> {
static const int value = 3; // not defined anywhere
};
} }
int foo (int val) { // was used by old logger
return val;
}
int bar (const int &val) { // is used by new logger
return val;
}
int main () {
// return bar(boost::serialization::version<Klass>::value); // link error
return foo(boost::serialization::version<Klass>::value); // works fine
}
因此,如果使用成员,则没有链接错误,但不查询其地址。通过引用传递值符合查询地址的条件。
相关文章:
- 用于访问容器<T>数据成员的正确 API
- 静态数据成员的问题-修复链接错误会导致编译器错误
- 数据成员SFINAE的C++17测试:gcc vs clang
- 派生类是否可以在抽象工厂设计模式中具有数据成员
- 如何在c++中定义以struct为数据成员的类中的构造函数
- 静态数据成员模板专用化的实例化点在哪里
- int数据类型的指针指向的是什么,如果是一个类的私有数据成员,我们创建了该类的两个对象?
- 使用指针访问数组中的对象数据成员
- 友元函数无法访问私有数据成员 (c++)
- 我可以在 C++ 中将数据成员/变量从其定义之外添加到结构中吗?
- 为什么将一个结构的引用设置为等于另一个结构只会更改一个数据成员?
- 将私有数据成员添加到野牛生成的类中
- 输入数据成员未按要求工作
- 二维矢量数据成员
- 在类 A 中创建类型为 B 类的向量 - 访问数据 [C++] [成员在两个类中都是私有的]
- 调用在 HXX 文件中声明的静态数据成员
- 是否可以根据其数据成员的类型确定类型的大小
- 访问数据成员(本身是对象)的数据成员,就好像它们是类成员一样
- 使公共数据成员在C++中无法访问
- 何时需要定义类的静态数据成员 (un/-)