Стандарт С++ требует, чтобы динамическая инициализация статических переменных выполнялась в основном потоке?

Требует ли стандарт С++ динамическую инициализацию нелокальных статических переменных в том же потоке, который вызывает main()?

В частности, в С++ 11 гарантируется, что std::this_thread::get_id() возвращает тот же результат в статических инициализаторах и внутри main()?

Edit:

Более конкретно, учитывая следующий код:

#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;
}

- два идентификатора потока, требуемые/гарантированные для соответствия?

Ответы

Ответ 1

Стандарт ничего не говорит о том, какой поток должен выполнять такую ​​инициализацию. Это требует только определенных заказов и гарантий:

3.6.2 Инициализация нелокальных переменных [basic.start.init]

2. Статическая инициализация должна выполняться до начала любой динамической инициализации. [...] Переменные с упорядоченной инициализацией, определенные в одной единице перевода, должны быть инициализированы в порядке их определений в блоке перевода. [...] Если программа запускает поток, последующая инициализация переменной не зависит от инициализации переменной, определенной в другой единицы перевода. В противном случае инициализация переменной неопределенно секвенирована относительно инициализации переменной, определенной в другой единицы перевода.

4. Определяется реализацией, выполняется ли динамическая инициализация нелокальной переменной со статической продолжительностью хранения до первого оператора main. Если инициализация отложена до некоторого момента времени после первого утверждения main, это должно произойти до первого odr-использования любой функции или переменной, определенной в той же самой единицы перевода, что и инициализированная переменная.

5. Определяется реализацией, выполняется ли динамическая инициализация нелокальной переменной со статикой или длительностью хранения потоков до первого утверждения начальной функции потока. Если инициализация отложена до некоторого момента времени после первого утверждения исходной функции потока, она должна произойти до первого использования odr любой переменной с длительностью хранения потока, определенной в той же самой единицы перевода, что и инициализированная переменная.

Однако большинство реализаций это сделают - инициализация статических нелокальных переменных будет выполняться в том же потоке, который вызывает main(). Пример из Visual С++ 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():

enter image description here

Ответ 2

Нет. Стандарт нигде не обеспечивает такую ​​гарантию, и на самом деле это противоречит [basic.start.init]/p2:

Если программа запускает поток (30.3), последующая инициализация переменная не зависит от инициализации переменная, определенная в другой единицы перевода. В противном случае инициализация переменной неопределенно упорядочена с учетом к инициализации переменной, определенной в другом переводе Блок. Если программа запускает поток, последующие неупорядоченные инициализация переменной не зависит от каждой другая динамическая инициализация. В противном случае неупорядоченная инициализация переменной неопределенно секвенируют по отношению ко всем другим динамическая инициализация.

Не было бы необходимости ослабить гарантию последовательности при наличии потоков, если бы все инициализации выполнялись в одном и том же потоке.

Ответ 3

Нет, хотя может быть хорошей идеей написать вашу программу таким образом. Синтаксис требует, чтобы статическая инициализация происходила детерминированным образом, но не диктует такие вещи, как задействованный поток.