我有一个程序分成两个源文件:
example.cpp
#include <iostream>
class A {
public:
A(int x) {
::std::cout << "In A(" << x << ")n";
}
};
static A first(1);
static A second(2);
__ main.cpp
int main(int argc, const char *argv[])
{
return 0;
}
这个程序的输出是否保证是:
In A(1)
In A(2)
在所有平台和编译器上?如果是这样,标准在哪里这么说?如果我使用名称空间,first
和second
出现在不同的名称空间中,这有关系吗?如果它们不是静态的,而我使用的是匿名命名空间呢?
是的,如果声明出现在同一翻译单元中,则为非局部静态对象定义初始化顺序。
源自c++ 03,
(3.6/2)在命名空间作用域中定义了静态存储时间的对象应初始化相同的翻译单元和动态初始化按照它们的定义在译文中出现的顺序单位。[注:8.5.1描述了聚合成员的顺序。初始化。描述了局部静态对象的初始化在6.7。)
在一个翻译单元中,全局变量是分几个阶段初始化的:
-
首先,所有具有"静态初始化"的变量都按照声明顺序初始化(见下文)。
-
然后,执行所有的"有序动态初始化",还是按照声明的顺序。
-
还有"无序动态初始化",相对于其他动态初始化(但总是在静态初始化之后),它们是"无序的"。
静态初始化和有序动态初始化的全局变量的销毁顺序相反(无序的全局变量也是"未排序的",但在静态全局变量之前)。跨tu的相对初始化顺序未指定。
松散地解释术语:一个全局变量是"静态初始化",如果它被初始化为常量(对于构造函数调用,这需要constexpr
构造函数),或者如果它没有初始化并被声明为static
(这使它零初始化):static int a; Foo b(1, true, Blue);
另一方面,如果初始化器不是任何"常量",如函数调用或非constexpr构造函数,那么对象是"动态初始化"。大多数动态初始化的普通全局变量都是"有序的";唯一的"无序"成员是模板特化的静态成员,诸如此类。
(注意,所有这些在c++ 11中变得更加详细,因为现在在线程开始时明确关注线程本地存储和初始化。)