Я вполне уверен, что глобально объявленные переменные выделяются (и инициализируются, если применимо) во время запуска программы.
int globalgarbage;
unsigned int anumber = 42;
Но как насчет статических, определенных в функции?
void doSomething()
{
static bool globalish = true;
// ...
}
Когда выделяется место под globalish
? Я догадываюсь, когда программа запустится. Но инициализируется ли он тоже? Или инициализируется при doSomething()
первом вызове?
Некоторое релевантное словоблудие из стандарта C ++:
источник
If the initialization exits by throwing an exception, the initialization is not complete, so it will be tried again the next time control enters the declaration.
Память для всех статических переменных выделяется при загрузке программы. Но локальные статические переменные создаются и инициализируются при первом использовании, а не при запуске программы. Там какая - то хорошее чтение об этом, и статика в целом, здесь . В общем, я думаю, что некоторые из этих проблем зависят от реализации, особенно если вы хотите знать, где в памяти будут расположены эти вещи.
источник
Компилятор выделяет статические переменные, определенные в функции
foo
при загрузке программы, однако компилятор также добавит некоторые дополнительные инструкции (машинный код) к вашей функции,foo
чтобы при первом вызове этот дополнительный код инициализировал статическую переменную ( например, вызов конструктора, если применимо).@Adam: Эта закулисная инъекция кода компилятором является причиной того результата, который вы видели.
источник
Я пытаюсь еще раз протестировать код Адама Пирса и добавил еще два случая: статическая переменная в классе и тип POD. Мой компилятор - g ++ 4.8.1 в ОС Windows (MinGW-32). Результат - статическая переменная в классе обрабатывается так же, как и глобальная переменная. Его конструктор будет вызван перед входом в основную функцию.
Вывод (для g ++, среда Windows):
(1) : Правильное состояние должно быть: «до вызова любой функции из той же единицы трансляции». Однако для простых, как в примере ниже, это основная функция.
включить <iostream>
#include < string> using namespace std; class test { public: test(const char *name) : _name(name) { cout << _name << " created" << endl; } ~test() { cout << _name << " destroyed" << endl; } string _name; static test t; // static member }; test test::t("static in class"); test t("global variable"); void f() { static test t("static variable"); static int num = 10 ; // POD type, init before enter main function test t2("Local variable"); cout << "Function executed" << endl; } int main() { test t("local to main"); cout << "Program start" << endl; f(); cout << "Program end" << endl; return 0; }
результат:
static in class created global variable created local to main created Program start static variable created Local variable created Function executed Local variable destroyed Program end local to main destroyed static variable destroyed global variable destroyed static in class destroyed
Кто-нибудь тестировал в Linux env?
источник
Да, именно так. Это, среди прочего, позволяет вам инициализировать структуры данных с глобальным доступом, когда это необходимо, например, внутри блоков try / catch. Например, вместо
int foo = init(); // bad if init() throws something int main() { try { ... } catch(...){ ... } }
ты можешь написать
int& foo() { static int myfoo = init(); return myfoo; }
и используйте его внутри блока try / catch. При первом вызове переменная будет инициализирована. Затем при первом и следующем вызовах будет возвращено его значение (по ссылке).
источник
Статические переменные размещаются внутри сегмента кода - они являются частью исполняемого образа и поэтому отображаются в уже инициализированном виде.
Статические переменные в области видимости функции обрабатываются одинаково, область видимости является исключительно конструкцией уровня языка.
По этой причине вам гарантируется, что статическая переменная будет инициализирована значением 0 (если вы не укажете что-то еще), а не неопределенным значением.
Есть и другие аспекты инициализации, которыми вы можете воспользоваться - например, общие сегменты позволяют различным экземплярам вашего исполняемого файла, запущенным одновременно, обращаться к одним и тем же статическим переменным.
В C ++ (с глобальным охватом) у статических объектов конструкторы вызываются как часть запуска программы под управлением библиотеки времени выполнения C. В Visual C ++ по крайней мере порядок, в котором инициализируются объекты, можно контролировать с помощью прагмы init_seg .
источник