Когда встроенные переменные в статическом хранилище инициализируются?
Стандарты C++ (по крайней мере, ранее C++17) говорили об этом в порядке инициализации.
Объекты со статической продолжительностью хранения, определенной в области пространства имен в одной и той же единице перевода и динамически инициализированной, должны быть инициализированы в том порядке, в котором их определение появляется в единице перевода.
C++17 вводит встроенные переменные, которые, как я полагаю, означают, что одна переменная со статической продолжительностью хранения и областью имен и динамической инициализацией может быть определена в нескольких единицах перевода.
Делает ли C++ какие-либо гарантии относительно порядка инициализации этих переменных?
1 ответ
Смотрите [basic.start.dynamic] p1:
Динамическая инициализация нелокальной переменной со статической длительностью хранения неупорядочена, если переменная является неявно или явно созданной специализацией, частично упорядочена, если переменная является встроенной переменной, которая не является неявно или явно созданной специализацией, и в противном случае упорядочена,
Поэтому тип переменной, которую вы описываете, имеет "частично упорядоченную инициализацию". Согласно п2:
Динамическая инициализация нелокальных переменных
V
а такжеW
При статической длительности хранения упорядочиваются следующим образом:
- ...
- Если
V
имеет частично упорядоченную инициализацию,W
не имеет неупорядоченной инициализации, иV
определяется раньшеW
в каждой единице перевода, в которойW
определяется, то
- если программа запускает поток (4.7), отличный от основного потока (6.6.1), инициализация
V
сильно происходит до инициализацииW
;- в противном случае инициализация
V
последовательность перед инициализациейW
,- ...
Итак, подведем итог, предполагая, что на рисунке нет созданных экземпляров шаблонов:
- Если у вас есть две встроенные переменные пространства имен
V
а такжеW
такой, чтоV
определяется раньшеW
в каждой единице перевода, тоV
инициализируется раньшеW
, - Если только
V
встроенный, иW
некоторая не встроенная переменная пространства имен, определенная ровно в одной единице перевода,V
будет инициализирован раньшеW
так долго какV
определение предшествуетW
в этом едином переводческом блоке. - Если не встроенная переменная определена перед встроенной переменной, их порядок инициализации не может быть гарантирован. (По сути, вы можете себе представить, что реализация решает инициализировать единицы перевода в некотором порядке; она может выбрать одну из единиц перевода, содержащую только встроенную переменную, перед единицей перевода, которая содержит как встроенную переменную, так и не встроенную переменную.)
Также см. P5:
Это определяется реализацией, будет ли динамическая инициализация нелокальной встроенной переменной со статической продолжительностью хранения упорядочена перед первым оператором
main
или откладывается. Если оно откладывается, это сильно происходит перед любым использованием неинициализации odr этой переменной. Это определяется реализацией, в каких потоках и в каких точках программы происходит такая отложенная динамическая инициализация.