Подтвердить что ты не робот

Гарантия статической (постоянной) инициализации статических объектов

Общий вопрос: как программист может убедиться, что его нелокальные статические переменные инициализируются с помощью статической инициализации, а не посредством динамической инициализации?

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

3.6.2.2. Постоянным инициализатором для объекта o является выражение, которое является константным выражением, за исключением того, что оно также может ссылаться на constexpr конструкторы для o и его подобъектов, даже если эти объекты имеют нелиберальные типы классов [Примечание: такой класс может иметь нетривиальный деструктор-примечание]. Выполняется постоянная инициализация:

- если каждое полное выражение (включая неявные преобразования), которое появляется в инициализаторе ссылки со статикой или потоком длительность хранения - это постоянное выражение (5.19), и ссылка связанный с lvalue, обозначающим объект со статической продолжительностью хранения или к временному (см. 12.2);

- если объект со статикой или длительностью хранения потока инициализирован по вызову конструктора, и если полное выражение инициализации является постоянный инициализатор для объекта;

- если объект со статикой или длительностью хранения потоков не инициализируется вызовом конструктора, и если либо объект value-initialized или каждое полное выражение, которое появляется в его Инициализатор - это постоянное выражение.

Я опустил ссылку, поскольку это не важно в моем случае. Насколько я понимаю, стандарт состоит в том, что есть 3 случая:

  • т е р
  • no-ctor и инициализация значений
  • no-ctor и постоянное выражение

Скажем, у меня есть следующий класс:

struct X {
  bool flag = false;
  // = {} will break VS2013 CTP so in that case use the
  // regular ctor, which sadly still can't be declared constexpr
  std::aligned_storage<sizeof(int), alignof(int)>::type storage = {};
};

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

Требуется ли этому классу конструктор constexpr?

Является ли константная инициализация гарантированной для С++ 11, а также С++ 98?

Боковой вопрос: когда будет выполнена статическая инициализация в случае so/dll? В течение времени загрузки, или оно может быть отложено еще больше?

4b9b3361

Ответ 1

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

Однако тип инициализации не должен иметь значения, потому что требуемое пространство выделяется во время компиляции. В зависимости от того, как вы определяете переменную, она будет либо в разделе .bss или .data.

Инициализация, как вы знаете, заключается только в том, чтобы обеспечить конкретный контент в памяти до его первого использования. Если вы не определяете конструктор, который выделяет динамическую память, тогда динамического выделения не будет (если это ваша проблема).

Для простых конструкторов я считаю, что компилятор будет генерировать встроенный код и использовать его для инициализации объекта во время компиляции (я не уверен, что стандарт говорит об одном и том же, но возможно, что он зависит от цепочки инструментов). Со сложными конструкторами нелокальные статические объекты будут инициализироваться, когда изображение загружается в память, а локальные статические объекты будут инициализированы при загрузке фрейма стека. В любом случае перед первым использованием вы должны найти объект в известном состоянии.

Ответ 2

Боковой вопрос: когда статическая инициализация будет выполнена в случае так/длл? В течение времени загрузки, или оно может быть отложено еще больше?

В Windows статическая инициализация происходит до того, как вызывается DllMain() с приобретением блокировки загрузчика DLL. Это сильно ограничивает то, что вы можете сделать в конструкторах для ваших статических объектов. Вы не можете загружать любые другие DLL (LoadLibrary) или вызывать любую другую функцию, которая МОЖЕТ привести к загрузке DLL, что в значительной степени исключает что-либо помимо простой инициализации и функций, экспортируемых Kernel32.

Подробнее см. последние несколько абзацев DllMain (MSDN).