Например, есть искусственный пример: ...
int main() {
/*
некоторый код
*/
...{
static int someVal = 42;
}
}
Когда произойдет создание переменной? Во время запуска программы или когда доберемся до нужной инструкции?
Вопрос не имеет однозначного ответа, ибо ответ на него в общем случае критически зависит от типа объекта. В вашем конкретном примере с типом int - объект всегда создается строго во время запуска программы.
А в общем случае это зависит от того, что вы называете "созданием".
У объектов в С++ есть "период хранения" (storage duration) и "время жизни" (lifetime).
Период хранения - это период выделения-освобождения "сырой" памяти, занимаемой объектом.
Период хранения любых статических объектов - это всегда безусловно все время выполнения программы.
Время жизни - это период между [нетривиальной] инициализацией и [нетривиальной] деструкцией объекта в этой сырой памяти. Время жизни всегда вложено в период хранения. Время жизни зависит от свойств объекта.
Если инициализация объекта тривиальна (т.е. если это не-класс тип или класс тип, инициализируемый тривиальным конструктором по умолчанию), то конструкции не требуется вообще и начало периода хранения автоматически является началом времени жизни.
Аналогично если деструкция объекта тривиальна (т.е. если это не-класс тип или класс тип с тривиальным деструктором), то время жизни длится до конца периода хранения.
Если статический объект требует нетривиальной конструкции, то она будет выполнена в момент первого прохода процесса выполнения по объявлению объекта (если такой момент вообще наступит).
Также, если объект скалярного типа (такого как типа int) инициализируется константным выражением, то такая инициализация будет выполнена статически (еще на старте программы). Если же выражение неконстантно, на старте программы такой объект будет инициализирован нулем, а инициализация выражением будет выполнена позже, динамически. В случае объекта, объявленного локально, это произойдет в момент первого прохода процесса выполнения по объявлению объекта (если такой момент вообще наступит).
В вашем случае вы имеет дело с статическим объектом типа int. Период хранения такого объекта - все время выполнения программы. И так как это не-класс тип, время жизни этого объекта - все время выполнения программы. Также язык гарантирует вам, что инициализация этого объекта делается статически - не во время первого прохода выполнения по объявлению этого объекта, а сразу на старте программы.
Например, вот такой код гарантированно выведет 42
// Продолжительность хранения `i` уже началась
// Время жизни `i` уже началось
// `i` уже проинициализировано значением 42
int main()
{
goto skip;
static int i = 42; // Статическая инициализация
skip:
std::cout << i << std::endl;
}
А вот такой гарантированно выведет 0
// Продолжительность хранения `i` уже началась
// Время жизни `i` уже началось
// `i` уже проинициализировано значением 0
int main()
{
goto skip;
static int i = std::rand(); // Динамическая инициализация
skip:
std::cout << i << std::endl;
}
Если вы замените int на std::string, то период хранения такого объекта - все равно все время выполнения программы. А вот время жизни этого объекта начнется тогда, когда выполнение в первый раз пройдет по его объявлению (если такой момент вообще наступит).
Например, вот такой код
// Продолжительность хранения `s` уже началась
// Время жизни `s` еще не началось
// Однако все члены `s` уже проинициализированы нулями
int main()
{
goto skip;
static std::string s = "Hello World!"; // Динамическая инициализация и начало жизни
skip:
std::cout << s << std::endl;
}
увидит объект s, по которому пока что только успел проехаться каток огульной нулевой инициализации, но конструкции не выполнялось. Время жизни объекта так и не началось. Поведение не определено.
При первом выполнении кода.
Можно убедиться, создавая, например, переменную некоторого класса с конструктором.
struct Test
{
Test(int x) { cout << x << endl; }
};
int main()
{
for(int i = 0; i < 10; ++i)
{
cout << i << endl;
static Test t = 42;
}
}
Получим
0
42
1
2
3
4
5
6
7
8
9
А что такое создание переменной, как не вызов конструктора? :)
Подозреваю, что зависит от дальнейшего кода и/или настроек компилятора. Такой пример
static int someVal = 42;
printf ("0x%X", someVal);
Дает на выходе такой код:
.text:0040101E push 42
.text:00401020 push offset Format ; "0x%X"
.text:00401025 call esi ; __imp__printf
То есть переменной как таковой и нет, компилятор соптимизировал ее в константу. А вот такой код:
printf ("0x%X", someVal);
someVal++;
printf ("0x%X", someVal);
Приводит к созданию глобальной переменной, инициализированной во время компиляции.
Апостиль в Лос-Анджелесе без лишних нервов и бумажной волокиты
Основные этапы разработки сайта для стоматологической клиники
Продвижение своими сайтами как стратегия роста и независимости