Страницы

Поиск по вопросам

понедельник, 1 октября 2018 г.

Время создания переменной

Например, есть искусственный пример: ...
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, по которому уже успел проехаться каток огульной нулевой инициализации, но конструкции еще не выполнялось. Время жизни объекта так и не началось. Поведение не определено.

Комментариев нет:

Отправить комментарий