为什么即使存在此静态成员,也不会构造它?
Why is this static member not constructed even though it exists?
前几天我遇到了一些意想不到的行为,并将其简化为这几行代码。我在VC++ 19.0,Clang 3.8和GCC 5.4.0以及8.2.0上对其进行了测试。每种情况下的输出都只有1
,而我原本期望它以Hello
开头,以Goodbye
完成。
#include <iostream>
template <class T> struct X { static T data; };
template <class T> T X<T>::data;
struct A
{
A()
{
std::cout << "Hello" << std::endl;
}
~A()
{
std::cout << "Goodbye" << std::endl;
}
};
struct B : X<A> { };
int main(int argc, char **argv)
{
std::cout << sizeof(B::data) << std::endl;
}
显然B::data
存在,但从未调用其构造函数和析构函数。有趣的是,如果我将其添加到测试中
assert(typeid(B::data) == typeid(A));
GCC 的行为与我最初预期的那样,但 Clang 和 VC++ 的行为都像以前一样。所以我在这里的怀疑是,这种行为是不确定的,而不仅仅是出乎意料的。我对语言标准措辞不够熟悉,无法自己确切地说出在这种情况下的违规行为是什么。但它肯定违背了我对静态成员和继承如何工作的直觉。
根据 [temp.inst]/3:
。特别是,静态数据成员的初始化(以及任何关联的副作用(不会发生,除非静态数据成员本身的使用方式要求存在静态数据成员的定义。
和 [expr.context]/1:
[注意:在未计算的操作数中,可以命名非静态类成员([expr.prim.id](,并且对象或函数的命名本身不需要提供定义([basic.def.odr](。
X<A>::data
只用作sizeof
的操作数,这是一个未求值的操作数,因此X<A>::data
没有初始化。
对于typeid
的情况,我认为这是一个GCC错误。
访问结构的静态成员不会实例化它,因此永远不会调用您情况下struct X<A>
的构造函数。
您甚至可以简化代码以在没有模板的情况下尝试,因为它不会影响此处的结果。
相关文章:
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- 如何在C++中使用非静态成员函数作为回调函数
- (C++)为什么静态成员可以在初始化之前使用
- 类的全局对象和静态成员
- 在作为静态成员包含在另一个类中的类的构造函数中使用 cout
- 模板化类中静态成员的延迟初始化
- 使用静态成员声明类时遇到问题
- C++:是否可以使用非静态成员变量模板?
- 静态成员函数使用相同的名称时出现模板类型名称错误
- 如何在复杂继承中访问静态成员变量
- 在 nullptr 上调用无状态类的非静态成员函数是否合法?
- 检查编译时是否存在静态函数
- 如何在友元函数中使用静态成员而不添加前缀 [类名]::
- 为什么即使存在此静态成员,也不会构造它?
- 使用C ,使用SFINAE测试静态成员的存在,返回错误的值
- 在不存在的对象上调用静态成员函数
- 存在静态常量成员时的赋值运算符
- 如何检查SFINAE是否存在静态常量成员
- 是否存在阻止内置具有静态成员的技术限制
- 如何检测具有特定签名的静态成员函数的存在