Когда инициализируется глобальная переменная `thread_local`?

Рассмотрим следующий пример (блокировка охранников на 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;
}

И на clang, и на gcc эта программа ничего не выводит, если пользователь пишет «0», пока печатает Constructor/Destructor 10 раз, если пользователь вводит ненулевое число.
Кроме того, Clang жалуется на очевидный неиспользованный результат выражения.

Так как thread_local срок хранения должен охватывать весь поток, я ожидал foo переменная, которая будет инициализирована в каждом потоке, независимо от пользовательского ввода.

Я мог бы хотеть иметь thread-local переменная с единственной целью иметь побочный эффект в конструкторе, делает ли стандартный мандат, что thread_local объект инициализируется при первом его использовании?

17

Решение

Стандарт допускает такое поведение, хотя и не гарантирует его. От 3.7.2 / 2 [basic.stc.thread]:

Переменная с продолжительностью хранения потока должна быть инициализирована до
его первое использование odr (3.2) и, если оно будет построено, должно быть уничтожено
выход из нити.

Также возможно, что объекты создаются в какое-то другое время (например, при запуске программы), поскольку «перед первым использованием» означает «в любой момент до тех пор, пока это происходит до», а не «непосредственно перед».

18

Другие решения


По вопросам рекламы [email protected]