Статические простые типы С++ инициализируются по порядку?

Мой опыт говорит мне, что данный объект:

class Object
{
private:
    static int array[];

public:
    Object(int id);
};


int Object::array[] = { 2937, 892 };


Object::Object(int id)
{
    // do something
}

Инициализация array произойдет до вызова любого метода для Object или вызова любого метода для любого другого объекта в программе, независимо от того, объявлен ли этот объект static или нет.

По сути, я спрашиваю, не согласен ли кто-нибудь с тем, что статические простые типы C (не объекты), такие как char, short, int и long (и структуры без конструкторов, состоящие из этих типов), инициализируются, когда исполняемый файл загружается в память, перед вызовом main() или любого другого конструктора?


person Matthew    schedule 15.10.2010    source источник


Ответы (5)


Да, вся статическая инициализация происходит до вызова main(). Но вы не можете быть уверены, в каком порядке происходит инициализация. Это может вызвать хаос, когда одна статическая переменная зависит от существования другой. Это называется фиаско статической инициализации: http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.14

Я часто использую решение, упомянутое в faq. Используйте функции со статическими переменными внутри, чтобы лучше контролировать порядок.

person miked    schedule 15.10.2010
comment
Только FAQ называет это фиаско. 1) Также обратите внимание, что порядок четко определен в единице компиляции. 2) В любом случае у вас не должно быть так много глобалов. 3) Глобалы, которые совершенно не связаны друг с другом, не должны зависеть друг от друга (если они есть, они будут в одной единице компиляции). Так что вряд ли это фиаско, поскольку это единственная реальная проблема, если вы совершенно некомпетентны (т.е. не следуете каким-либо передовым методам). - person Martin York; 16.10.2010

Конкретный тип инициализации, о котором, я думаю, вы говорите:

По сути, я спрашиваю, кто-нибудь не согласен с тем, что статические простые типы C (не объекты), такие как char, short, int и long (и структуры без конструкторов, состоящие из этих типов), инициализируются, когда исполняемый файл загружается в память, перед вызовом main() или любого другого конструктора?

Я предполагаю, что вы имеете в виду, что инициализация с помощью констант - не вызовом функции. Если это предположение верно, то да, вы можете быть уверены, что инициализация произойдет до вызова каких-либо конструкторов:

  • 3.6.2 инициализация нелокальных объектов

Объекты со статической продолжительностью хранения (3.7.1) должны быть инициализированы нулями (8.5) до того, как произойдет любая другая инициализация. Нулевая инициализация и инициализация с константным выражением вместе называются статической инициализацией; вся остальная инициализация является динамической инициализацией. Объекты типов POD (3.9) со статической продолжительностью хранения, инициализированные константными выражениями (5.19), должны быть инициализированы до любой динамической инициализации. Объекты со статической продолжительностью хранения, определенной в области пространства имен в той же единице трансляции и динамически инициализированные должны быть инициализированы в том порядке, в котором их определение появляется в единице перевода.

Однако инициализация, такая как

static int x = getvalue();

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

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

person Michael Burr    schedule 15.10.2010
comment
Да, и определение типа POD становится техническим, но в значительной степени соответствует концепции OP, описывающей простые типы C... и структуры без конструкторов, состоящие из этих типов. (Кроме того, он рекурсивный, поэтому вы можете иметь структуры в структурах.) - person aschepler; 16.10.2010

Это действительно так. Что не гарантируется, так это порядок, в котором статические члены в разных единицах перевода инициализируются относительно друг друга.

person Oliver Charlesworth    schedule 15.10.2010

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

Я думаю, что любой приличный компилятор сделает это. Затем, когда ваш exe загружается в память, он уже имеет жестко закодированные значения.

person Klaim    schedule 15.10.2010

Стандарт только говорит, что статика инициализируется до того, как управление входит в область, в которой к ней можно получить доступ. Ничего другого это не определяет. Я думаю, что переменные файловой области — это другое, но в целом использование статики и зависимость от статического поведения — плохая идея.

person Puppy    schedule 15.10.2010