Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/129.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 文件中模板类的静态数据成员的初始化顺序是什么?_C++_Class_Templates_Static Members - Fatal编程技术网

C++ 文件中模板类的静态数据成员的初始化顺序是什么?

C++ 文件中模板类的静态数据成员的初始化顺序是什么?,c++,class,templates,static-members,C++,Class,Templates,Static Members,在给定的文件中,如果我有 struct A { static int a; }; struct B { static int b; }; int A::a; int B::b; 然后,我可以期望A::A在B::B之前得到初始化。现在,对于同一个文件,以模板为例 template<typename T> struct X { static T t; }; template<typename T> T X<T>::t; 模板 结构X{static T;}; 模

在给定的文件中,如果我有

struct A { static int a; };
struct B { static int b; };
int A::a;
int B::b;
然后,我可以期望
A::A
B::B
之前得到初始化。现在,对于同一个文件,以
模板
为例

template<typename T>
struct X { static T t; };
template<typename T>
T X<T>::t;
模板
结构X{static T;};
模板
tx::T;

假设,
X
A
B
实例化,其
静态
成员在代码中任意使用为,
X::t
X::t
,那么
模板
静态成员
X::t>的初始化顺序应该是什么?它定义得好吗?

以下是我的观察结果(基于gcc):

任何首先出现的东西都会首先实例化

如果在给定的翻译单元(即预处理的
.cpp
文件)中,如果编译器(解析器)首先看到用法
X::t
,则首先实例化,或者如果它首先看到
X::t
,则首先实例化。注意,这是在编译之前(不是运行时)

比如说,

struct A { static int a; };
struct B { static int b; };

template<typename T> struct X { static T t; };
template<typename T> T X<T>::t;

void foo ()
{
  B *p = &(X<B>::t);
}

int main ()
{
  A *p = &(X<A>::t);
  foo();
}
结构A{static int A;}; 结构B{static int B;}; 模板结构X{static T;}; 模板tx::T; void foo() { B*p=&(X::t); } int main() { A*p=&(X::t); foo(); }
结果:

X<B>::t instantiated first
X<A>::t instantiated second
X::t首先实例化
X::t实例化的第二个
原因:

X::t
首先出现在
foo()中

根据第3.6.2节:

具有静态存储持续时间的非局部变量的动态初始化可以是有序的,也可以是无序的。显式专用类模板静态数据成员的定义已按顺序初始化。其他类模板静态数据成员(即隐式或显式实例化的专门化)具有无序初始化。具有静态存储持续时间的其他非局部变量已命令初始化。在单个翻译单元中定义了有序初始化的变量应按照其在翻译单元中定义的顺序进行初始化

因此,为了回答您的问题,显式实例化模板的静态数据成员不能保证在C++0x中以任何特定顺序初始化

我将其留给其他人在早期标准中查找相应的语言(或缺少该语言)。

从14.7.2/7开始:

类模板专门化的显式实例化意味着 它的所有成员的实例化以前没有显式地 专门从事包含显式 实例化

因此,我们可以得出结论,显式实例化的模板的静态成员的实例化/构造顺序相同

但是,对于隐式实例化的模板,我们转到14.7.1/1:

…特别是,初始化(以及任何相关的副作用) 静态数据成员不会出现,除非该静态数据成员是 它本身的使用方式需要定义静态数据 成员必须存在


从这一点上,我不认为我们可以安全地得出任何关于隐式实例化模板的实例化顺序的结论。

只要模板只有一个定义(例如,您只有一个翻译单元),它就是定义良好的。静态成员按照模板专门化在需要定义静态数据成员的上下文中实例化的顺序进行初始化。根据C++03标准的§14.7.1/1[临时说明](重点说明):

除非类模板专门化已显式实例化(14.7.2)或显式专门化(14.7.3),当在需要完全定义的对象类型的上下文中引用专门化时,或者当类类型的完整性影响程序的语义时,将隐式实例化类模板专门化。类模板专门化的隐式实例化导致类成员函数、成员类、静态数据成员和成员模板的声明隐式实例化,而不是定义或默认参数的隐式实例化;它导致成员匿名联合定义的隐式实例化。除非类模板或成员模板的成员已显式实例化或显式专门化,否则当在要求成员定义存在的上下文中引用专门化时,该成员的专门化将隐式实例化特别是,静态数据成员的初始化(以及任何相关的副作用)不会发生,除非静态数据成员本身的使用方式要求静态数据成员的定义存在。

§14.7.1/7还规定:

类模板的隐式实例化不会导致隐式实例化该类的任何静态数据成员

但是,当您有多个定义模板的翻译单元时,事情会变得更加复杂。§3.2/5[基本定义odr]规定:

类类型(第9条)、枚举类型(7.2)、带外部链接的内联函数(7.1.2)、类模板(第14条)、非静态函数模板(14.5.5)、类模板的静态数据成员(14.5.1.3)、类模板的成员函数(14.5.1.1)可以有多个定义,或在程序中未指定某些模板参数(14.7、14.5.4)的模板专用化,前提是每个定义出现在不同的翻译单元中,并且定义满足以下要求。给定在多个翻译单元中定义的名为D的实体,则

(条件清单…)

如果D的定义满足所有这些要求,则程序的行为应与D的定义相同。如果D的定义不满足这些要求,则