C ++标准是否要求在调用main()
的同一线程中执行非本地静态变量的动态初始化?
更具体地说,在C ++ 11中,std::this_thread::get_id()
是否保证在静态初始值设定项和main()
内返回相同的结果?
修改
更具体地说,给出以下代码:
#include <iostream>
#include <thread>
static std::thread::id id = std::this_thread::get_id();
int main()
{
std::cout << id << "\n";
std::cout << std::this_thread::get_id() << "\n";
return 0;
}
是否需要/保证匹配的两个发出的线程ID?
答案 0 :(得分:5)
没有。标准无处可提供这样的保证,实际上相反的是[basic.start.init] / p2:
如果程序启动一个线程(30.3),则后续初始化 关于a的初始化,变量未被排序 变量在不同的翻译单元中定义。否则, 关于变量的初始化是不确定地排序的 初始化在不同翻译中定义的变量 单元。如果程序启动一个线程,则后续无序 变量的初始化对每个变量都是无序的 其他动态初始化。否则,无序初始化 变量的变量相对于彼此不确定地排序 动态初始化。
如果必须在同一个线程上执行所有初始化,则无需在线程存在时削弱排序保证。
答案 1 :(得分:0)
不,尽管以这种方式编写程序可能是个好主意。语法要求静态初始化以确定的方式发生,但不会像所涉及的线程那样指示。
答案 2 :(得分:0)
标准没有说明什么线程应该执行这样的初始化。它只需要特定的订单和保证:
3.6.2非局部变量的初始化 [basic.start.init]
2. 静态初始化应在进行任何动态初始化之前执行。 [...]在单个翻译单元中定义的具有有序初始化的变量应按其在翻译单元中的定义顺序进行初始化。 [...]如果程序启动一个线程,则对于在不同转换单元中定义的变量的初始化,后续的变量初始化是未排序的。否则,对于在不同转换单元中定义的变量的初始化,变量的初始化是不确定的。
4. 实现定义是否在第一个main语句之前完成具有静态存储持续时间的非局部变量的动态初始化。如果初始化延迟到某个时间点 在第一个main语句之后,它应该在与要初始化的变量相同的翻译单元中定义的任何函数或变量的第一次使用之前发生。
5. 实现定义是否在线程初始函数的第一个语句之前完成具有静态或线程存储持续时间的非局部变量的动态初始化。如果初始化被推迟到线程初始函数的第一个语句之后的某个时间点,它应该在任何变量的第一次使用之前发生,其中线程存储持续时间在与要初始化的变量相同的转换单元中定义
但是,大多数实现都会这样做 - 静态非局部变量的初始化将在调用main()
的同一线程中执行。 Visual C ++ 11中的示例:
#include <iostream>
#include <thread>
using namespace std;
struct Cx
{
public:
Cx()
{
cout<<"Cx: "<<std::this_thread::get_id()<<endl;
}
};
static Cx c;
int main()
{
cout<<"Main: "<<std::this_thread::get_id()<<endl;
return 0;
}
输出:
Cx: 5820
Main: 5820
在Cx::Cx()
内设置断点后: