Пространства имен влияют на порядок инициализации в С++?
Глобальные переменные инициализируются в порядке появления в модуле трансляции и относительном порядке инициализации переменных в разных модулях перевода в неуказанном (так называемый "статический фиаско порядка инициализации" ).
Влияют ли пространства имен на это? Например, если у меня есть этот код:
//first.cpp
int first;
int second;
будет ли она иметь какую-либо разницу в порядке инициализации по сравнению с этим кодом:
//second.cpp
namespace {
int first;
}
int second;
Существуют ли случаи, когда помещение глобального объекта в пространство имен влияет на порядок инициализации?
Ответы
Ответ 1
3.6 Другие нелокальные переменные со статическим временем хранения заказали инициализацию. переменные с упорядоченной инициализацией, определенной в пределах одной единицы перевода, должны быть инициализированы в порядке их определения в блоке перевода.
Пространства имен не влияют на это - не упомянуты в разделе.
Что влияет на порядок разных единиц перевода. Если вам нужно определить порядок между ними, используйте расширение, такое как атрибут GCC constructor
.
Ответ 2
Ну, "Глобальные переменные инициализируются в порядке появления в модуле перевода". Это не оставляет места ни для чего другого, например для пространств имен, чтобы повлиять на порядок.
Собственно, "глобальные переменные инициализируются по порядку..." - это неточное цитирование стандарта, как формально неверное. Точная формулировка из стандарта С++ Standard, ISO/IEC 14882: 2003, 3.6.2, пункт 1:
Объекты со статической продолжительностью хранения, определенные в области пространства имен в том же переводе единица и динамически инициализируется, должны быть инициализированы в том порядке, в котором их определение появляется в блоке трансляции.
Итак, вместо "global" он говорит "со статическим хранилищем", то есть все нелокальные переменные, являются ли они глобальными, членами пространства имен или членами класса и объявлены ли они static
или нет.
Также он добавляет "и динамически инициализируется". Переменные с тривиальными конструкторами и постоянным инициализатором всегда инициализируются сначала (просто загружая их значения из двоичного файла), и все не константные инициализаторы оцениваются, а нетривиальные конструкторы выполняются в этом порядке. Это важно, поэтому вы можете, например, надежно создать связанный список в этих конструкторах; если голова является простым указателем, она уже инициализирована, поэтому вы можете безопасно работать с ней.