Динамическая инициализация в с++
Недавно вычитал вот тут, что одна и та же переменная может быть динамически инициализирована после того, как она была статически инициализирована. Верно ли это? Если да, то разве можно инициализировать переменную 2 раза? Получается, что во время второй инициализации происходит не инициализация а присваивание
Ответы (1 шт):
Недавно вычитал вот тут, что одна и та же переменная может быть динамически инициализирована после того, как она была статически инициализирована. Верно ли это? Если да, то разве можно инициализировать переменную 2 раза?
Да, верно. Да, переменная может быть инициализирована дважды.
Это скорее вопрос терминологический: правильно ли называть вторую инициализацию инициализацией... Стандарт языка говорит, что в начале выполнения программы переменные со статическим классом хранения подвергаются статической инициализации (static initialization). Затем в процессе выполнения программы они могут быть дополнительно подвержены динамической инициализации (dynamic initialization).
Факт двойной инициализации вполне можно обнаружить на практике. basic.start.static/Note 2:
#include <iostream>
using std::cout;
using std::endl;
inline double fd() { return 1.0; }
extern double d1;
double d2 = d1; // unspecified:
// may be statically initialized to 0.0 or
// dynamically initialized to 0.0 if d1 is
// dynamically initialized, or 1.0 otherwise
double d1 = fd(); // may be initialized statically or dynamically to 1.0
int main() {
cout << "d1: " << d1 << endl;
cout << "d2: " << d2 << endl;
}
Вывод данной программы (g++, clang):
d1: 1
d2: 0
Наблюдаемое поведение можно объяснить следующим образом.
- Переменные
d1иd2статически инициализируются нулём. - Затем переменная
d2динамически инициализируется значением переменнойd1(double d2 = d1;). - Наконец, переменная
d1динамически инициализируется результатом вызова функцииfd(double d1 = fd();).
Впрочем, тут не всё так просто. Если не брать во внимание переменную d2, то код
inline double fd() { return 1.0; }
double d1 = fd();
в общем-то эквивалентен такому коду:
double d1 = 1.0;
Динамическую инициализацию переменной d1 можно заменить статической инициализацией, при этом значение переменной d1 не изменится. Стандарт языка явно разрешает делать такую замену. См.: basic.start.static/3. На этапе статической инициализации переменной d1 может быть присвоено значение 1.0, а не 0.0. Т.е. наблюдаемое поведение может быть и таким:
- Переменная
d1статически инициализируется значением1.0, а переменнаяd2статически инициализируется значением0.0. - Затем переменная
d2динамически инициализируется значением переменнойd1(т.е. также принимает значение1.0).
Наконец, так как переменной d2 в конечном итоге присваивается некоторое вполне конкретное значение, известное на этапе компиляции, то она, также как и переменная d1, может не подвергаться динамической инициализации, а только статической.
Как-то так.