例如,以下代码段中的node::node()
构造函数访问全局node::count
和::tail
,而没有任何多线程防护。 C ++标准是否保证输出始终是0 1 2
的排列(无论顺序如何)?
#include <stdio.h>
struct node *tail;
struct node
{
static int count;
int index;
node *prev;
node()
{ index = count++; prev = tail; tail = this; }
};
int node::count;
node one, two[2];
int main(int argc, char *argv[])
{
for(node *p = tail; p; p = p->prev)
printf("%d\n", p->index);
return 0;
}
我正在寻找基于(适用)标准的答案,而不是针对实现或编译器特定行为。关于SO有许多相关问题,但它们并不完全清楚它们如何直接应用于这个特殊而且相当基本的案例(Is C++ static member variable initialization thread-safe?,Is local static variable initialization thread-safe in C++11?等)。
答案 0 :(得分:5)
只要程序本身没有启动线程(例如在某个全局变量的构造函数中),全局变量的初始化就保证是单线程的。一旦发生这种情况,就可以在一定程度上实现剩余的初始化。
[basic.start.init] / 2 ...在单个翻译单元中定义的有序初始化变量应按其在翻译单元中的定义顺序进行初始化。如果程序启动一个线程(30.3),则对于在不同转换单元中定义的变量的初始化,后续的变量初始化是未排序的。否则,对于在不同转换单元中定义的变量的初始化,变量的初始化是不确定地排序的。如果程序启动一个线程,则对于每个其他动态初始化,后续无序的变量初始化都是无序的。否则,对于每个其他动态初始化,变量的无序初始化是不确定地排序的。 [注意:此定义允许同时初始化一系列有序变量 与另一个序列。 -end note ]
&#34;不确定地排序&#34;是保证单线程执行的部分。根据定义,排序{before,after,indeterminately} 的概念仅在单个线程中有意义:
[intro.execution] / 13 在之前排序是...由单个线程执行的评估之间的关系......