什么时候初始化`thread_local`全局变量?

sba*_*bbi 18 c++ multithreading thread-local c++11

请考虑以下示例(cout为简单起见,省略了锁定保护).

#include <future>
#include <iostream>
#include <thread>

using namespace std;

struct C
{
  C() { cout << "C constructor\n";}
  ~C() { cout << "C destructor\n";}
};

thread_local C foo;

int main()
{
   int select;
   cin >> select;
   future<void> f[10];
   for ( int i = 0;i < 10; ++i)
       f[i] = async( launch::async,[&](){ if (select) foo; } );
   return 0;
}
Run Code Online (Sandbox Code Playgroud)

在clang和gcc上,如果用户写'0',该程序不输出任何内容,而如果用户输入非零数字则打印Constructor/ Destructor10次​​.另外clang抱怨明显的非使用表达结果.

由于thread_local存储生命周期应该跨越整个线程的生命周期,我期望foo在每个线程中初始化变量,而不管用户输入如何.

我可能想要一个thread-local变量,其唯一目的是在构造函数中产生副作用,标准是否要求thread_local在第一次使用时初始化对象?

Jon*_*Jon 19

该标准允许此行为,但不保证.从3.7.2/2 [basic.stc.thread]:

具有线程存储持续时间的变量应在其第一次使用(3.2)之前初始化,如果构造,则应在线程退出时销毁.

也可能在其他时间(例如在程序启动时)构造对象,因为"在第一次使用之前"意味着"在任何时刻,只要它在之前"而不是"在之前".

  • 这有点误导; 该标准规定,具有线程局部存储持续时间的变量必须在使用odr之前的某个时间进行初始化,但是当**将被初始化时,它并不完全强制**,并且甚至允许实现初始化此类变量即使变量永远不会被使用.如上所述:当变量使用odr时,它可以在**最新**初始化,但这种初始化可以在此之前的任何时间发生. (9认同)