Является ли локальная статическая переменная инициализацией потокобезопасной в С++ 11?
Я знаю, что это часто задаваемый вопрос, но, поскольку существует так много вариантов, я хотел бы переформулировать его и, надеюсь, иметь ответ, отражающий текущее состояние. Что-то вроде
Logger& g_logger() {
static Logger lg;
return lg;
}
Является ли конструктор переменной lg гарантированно работать только один раз?
Я знаю из предыдущих ответов, что в С++ 03 это не так; в проекте С++ 0x это принудительно. Но я бы хотел получить более четкий ответ
- В стандарте С++ 11 (не черновик) завершено ли поведение инициализации потокобезопасным?
- Если приведенное выше да, в последних последних выпусках популярных компиляторов, а именно gcc 4.7, vc 2011 и clang 3.0, они правильно реализованы?
Ответы
Ответ 1
Соответствующий раздел 6.7:
такая переменная инициализируется, когда первый элемент управления проходит через его объявление; такая переменная считается инициализированной после завершения ее инициализации. [...] Если элемент управления входит в объявление одновременно, а переменная инициализируется, одновременное выполнение должно ждать завершения инициализации.
Тогда есть сноска:
Реализация не должна вводить какой-либо тупик вокруг выполнения инициализатора.
Итак, вы в безопасности.
(Это, конечно, ничего не говорит о последующем доступе к переменной через ссылку.)
Ответ 2
- fno-threadsafe-statics также стоит упомянуть. В gcc:
Не используйте дополнительный код для использования подпрограмм, указанных в С++ ABI, для потоковой инициализации локальной статистики. Вы можете использовать этот параметр, чтобы немного уменьшить размер кода в коде, который не должен быть потокобезопасным.
Кроме того, посмотрите на старый поток Являются ли функции статических переменных потокобезопасными в GCC?