Sha*_*esh 7 c++ undefined-behavior language-lawyer c++17
查:
#include <iostream>
class C {
public:
explicit C(int id) { std::cout<<"Initialized "<<id<<"\n"; }
};
Run Code Online (Sandbox Code Playgroud)
1.cpp:
#include "C.h"
C global(1);
Run Code Online (Sandbox Code Playgroud)
2.cpp:
#include "C.h"
thread_local C thread(2);
int main() {}
Run Code Online (Sandbox Code Playgroud)
我的问题是:是否保证global会在之前初始化thread?
C++ 标准在这一点上有些含糊,据我所知。它说(来自 C++17 n4659草案):
[basic.start.static] 静态初始化
作为程序启动的结果,具有静态存储持续时间的变量被初始化。作为线程执行的结果,具有线程存储持续时间的变量被初始化。
按理说,“程序启动”发生在“线程执行”之前,但由于这两个表达式仅出现在标准中的那个地方,我正在寻求实际语言律师的建议。
我将使用 C++20 工作草案,因为那里的措辞更简洁一些,尽管真正的规则没有改变。
首先,就非本地而言,thread_local行为基本上类似于static:[basic.stc.thread]/2:
[注意:具有线程存储持续时间的变量按照 [basic.start.static]、[basic.start.dynamic] 和 [stmt.dcl] 中的规定进行初始化,如果构造了,则在线程退出时销毁 ([basic. start.term])。— 尾注 ]
是的,是笔记。但是声明的非本地对象thread_local基本上是static这样的。
现在,既没有global也thread没有常量初始化 - 所以两者都是零初始化,然后它们必须进行动态初始化。到[basic.start.dynamic]!
如果变量是隐式或显式实例化的特化,则具有静态存储持续时间的非局部变量的动态初始化是无序的,如果变量是不是隐式或显式实例化的特化的内联变量,则是部分有序的,否则是有序的.
我们的变量都不是特化的,也都不是内联的。所以两者都是有序的。
声明 D在声明 E 之前是出现顺序的,如果
- D 出现在与 E 相同的翻译单元中,或
- 包含 E 的翻译单元对包含 D 的翻译单元有接口依赖,
在任何一种情况下,都在 E 之前。
我们的声明彼此之间不是按外观顺序排列的。
具有静态存储持续时间的非局部变量 V 和 W 的动态初始化顺序如下:
好的,子项目 1:
如果 V 和 W 有有序初始化并且 V 的定义在 W 的定义之前是外观有序的,或者如果 V 有部分有序初始化,W 没有无序初始化,并且对于 W 的每个定义 E 都存在一个定义 D的 V 使得 D 在 E 之前出现顺序,
不适用。这是一个复杂的条件,但它并不适用。
否则,如果程序在初始化 V 或 W 之前启动了主线程以外的线程,则未指定 V 和 W 的初始化发生在哪个线程中;如果它们发生在同一线程中,则初始化是无序的。
不,没有线程。
否则,V 和 W 的初始化顺序不确定。
我们走了。global并且thread是不确定的排序。
另请注意:
具有静态存储持续时间的非局部内联变量的动态初始化是在 main 的第一条语句之前排序还是延迟,由实现定义。
和:
具有线程存储期的非局部非内联变量的动态初始化是在线程的初始函数的第一条语句之前排序还是延迟,由实现定义。
| 归档时间: |
|
| 查看次数: |
319 次 |
| 最近记录: |