到处都写到,如果存在带有相关静态变量的不同编译单元,则会出现问题。而且,如果静态变量存在于一个编译单元中,那应该没有问题:它们将按照其在文件中的位置顺序进行初始化。
但是我有这段代码:
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;
}
而且在进入main()函数之前,它在运行时失败,因为它会在初始化const C<T> C<T>::nullObj(false);
之前 尝试进行const B<T> B<T>::nullObj(0);
初始化。尽管他们在一个文件中的位置。
为什么它尝试在第一个静态变量之前初始化第二个静态变量?C ++ Standart中是否存在用静态初始化序列描述实际情况的章节?
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; };
然后B<_B>::nullObj
确实在C
构造函数需要它之前进行了初始化
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句