一个编译单元中的静态初始化

Ark*_*ady 5 c++ static templates

静态初始化以及描述的内容,在这里在这个网站,甚至在这里

在任何地方都写出如果存在具有相关静态变量的不同编译单元,则会出现问题.如果一个编译单元中存在静态变量,则应该没有问题:它们将按照它们在文件中的位置的顺序进行初始化.

但我有这个代码:

template <typename T>
class A{
public:
    int _data;
    T _obj;
    A(int data) :_data(data){}
};

template <typename T>
class B{
public:
    const static B<T> nullObj;
    B(int data) :_a(new A<T>(data)){}
    A<T> *_a;
};

template <typename T>
class C{
public:
    const static C<T> nullObj;
    C() :_a(nullObj._a){}
    C(bool t) :_a(B<T>::nullObj._a){
        _a->_data++; //FAILS HERE!
    }
    A<T> *_a;
};

template <typename T>
const B<T> B<T>::nullObj(0);

template <typename T>
const C<T> C<T>::nullObj(false);

class _B{};
class  _A{ public: _A(){}; C<_B> g; };

int main(){
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

并且在进入main()函数之前它在运行时失败,因为它在初始化const C<T> C<T>::nullObj(false); 之前 尝试const B<T> B<T>::nullObj(0);初始化.尽管他们在一个文件中的位置.

为什么它会尝试在第一个静态变量之前初始化第二个静态变量?C++ Standart中是否存在章节,其中描述了静态初始化序列的真实情况?

qua*_*dev 5

C++标准,第14.7.1节[temp.inst]:

除非已显式实例化或明确专门化类模板或成员模板的成员,否则在需要成员定义存在的上下文中引用特化时,将隐式实例化成员的特化; 特别是,除非静态数据成员本身以需要静态数据成员定义存在的方式使用,否则不会发生静态数据成员的初始化(以及任何相关的副作用)


C<T>以前是实例化的B<T>,所以初始化的顺序很明确,并且是:

1) const static C<T> nullObj;

2) const static B<T> nullObj;

由于C构造函数取消引用B<T>::nullObj._a,因此您具有未定义的行为.

解:

您必须B<_B>::nullObj以某种方式使用静态成员进行初始化,例如,如果您执行以下操作:

class _B{};
class _A{ public: _A() : b(B<_B>::nullObj) {}; B<_B> b; C<_B> g; };
Run Code Online (Sandbox Code Playgroud)

然后B<_B>::nullObj确实在C构造函数需要它之前初始化