Динамическая инициализация в с++

Недавно вычитал вот тут, что одна и та же переменная может быть динамически инициализирована после того, как она была статически инициализирована. Верно ли это? Если да, то разве можно инициализировать переменную 2 раза? Получается, что во время второй инициализации происходит не инициализация а присваивание


Ответы (1 шт):

Автор решения: wololo

Недавно вычитал вот тут, что одна и та же переменная может быть динамически инициализирована после того, как она была статически инициализирована. Верно ли это? Если да, то разве можно инициализировать переменную 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

Наблюдаемое поведение можно объяснить следующим образом.

  1. Переменные d1 и d2 статически инициализируются нулём.
  2. Затем переменная d2 динамически инициализируется значением переменной d1 (double d2 = d1;).
  3. Наконец, переменная 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. Т.е. наблюдаемое поведение может быть и таким:

  1. Переменная d1 статически инициализируется значением 1.0, а переменная d2 статически инициализируется значением 0.0.
  2. Затем переменная d2 динамически инициализируется значением переменной d1 (т.е. также принимает значение 1.0).

Наконец, так как переменной d2 в конечном итоге присваивается некоторое вполне конкретное значение, известное на этапе компиляции, то она, также как и переменная d1, может не подвергаться динамической инициализации, а только статической.

Как-то так.

→ Ссылка