C++ 为什么这个静态成员即使存在也不构造?

C++ 为什么这个静态成员即使存在也不构造?,c++,templates,inheritance,static,C++,Templates,Inheritance,Static,前几天我遇到了一些意想不到的行为,并将其简化为这几行代码。我在VC++19.0、Clang3.8、GCC5.4.0和8.2.0上进行了测试。每种情况下的输出都是1,而我原本希望它以Hello开头,以bye结尾 #include <iostream> template <class T> struct X { static T data; }; template <class T> T X<T>::data; struct A { A()

前几天我遇到了一些意想不到的行为,并将其简化为这几行代码。我在VC++19.0、Clang3.8、GCC5.4.0和8.2.0上进行了测试。每种情况下的输出都是
1
,而我原本希望它以
Hello
开头,以
bye
结尾

#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;
}

GCC的行为与我最初预期的一样,但Clang和VC++的行为与以前一样。因此,我怀疑这种行为是未定义的,而不仅仅是出乎意料的。我对语言标准的措词不太熟悉,无法为自己确切说明本案中的违规行为。但这显然违背了我关于静态成员和继承如何工作的直觉

访问结构的静态成员不会实例化它,因此在您的情况下,
struct X
的构造函数永远不会被调用

您甚至可以简化代码,在不使用模板的情况下进行尝试,因为它不会影响此处的结果。

根据:

。。。特别是,静态数据成员的初始化(以及任何相关的副作用)不会发生,除非静态数据成员本身的使用方式要求静态数据成员的定义存在

以及:

[ 注意:在未赋值的操作数中,可以命名非静态类成员([expr.prim.id]),而对象或函数的命名本身并不要求提供定义([basic.def.odr])- 尾注 ]

X::data
仅用作
sizeof
的操作数,该操作数是未赋值的操作数,因此
X::data
未初始化


对于
typeid
,我认为这是一个GCC错误。

您的第一个代码从未实例化过B对象。@NeilButterworth。应该在某个地方使用的是
X::data
。比如
static\u cast(B::data);
assert(typeid(B::data) == typeid(A));