Влияет ли пространство имен на порядок инициализации в C ++? - PullRequest
12 голосов
/ 02 декабря 2011

Глобальные переменные инициализируются в порядке их появления в модуле перевода и относительном порядке инициализации переменных в разных модулях перевода в неопределенном состоянии (так называемое «фиаско статического порядка инициализации»).

Какое влияние на это оказывают пространства имен? Например, если у меня есть этот код:

//first.cpp
int first;
int second;

будет ли разница в порядке инициализации по сравнению с этим кодом:

//second.cpp
namespace {
int first;
}
int second;

Существуют ли случаи, когда помещение глобального объекта в пространство имен влияет на порядок инициализации?

Ответы [ 2 ]

11 голосов
/ 02 декабря 2011

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

Пространства имен не влияют на это - не упоминается в разделе.

Что влияет на порядок, это разные единицы перевода.Если вам нужно определить порядок для них, используйте расширение, такое как атрибут constructor GCC.

5 голосов
/ 02 декабря 2011

Ну, «Глобальные переменные инициализируются в порядке появления в модуле перевода», это точно.Он не оставляет места для чего-либо еще, например, пространств имен, влиять на порядок.

На самом деле, «Глобальные переменные инициализируются по порядку ...» - это неточная цитата стандарта, так как формально неверна.Точная формулировка из стандарта C ++, ISO / IEC 14882: 2003, 3.6.2 параграфа 1:

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

Таким образом, вместо слова «глобальный» он говорит «со статическим хранилищем», то есть все нелокальные переменные, являются ли они глобальными, членами пространства именили члены класса и объявлены ли они static или нет.

Также он добавляет "и динамически инициализируется".Переменные с тривиальными конструкторами и инициализатором констант всегда сначала инициализируются (просто загружая их значения из двоичного файла), а затем оцениваются все неконстантные инициализаторы, и нетривиальные конструкторы выполняются в этом порядке.Это важно, так что вы можете, например, надежно создать связанный список в этих конструкторах;если его заголовок имеет простой указатель, он уже инициализирован, поэтому вы можете безопасно с ним работать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...