Если вы измените инициализацию cMyConstDouble2
на это здесь:
const double cMyConstDouble2 = 2.5*3.14;
Тогда ваша программа должна вести себя правильно. Причина этого в том, что переменные, которые
- Тип POD
- Инициализируются константными выражениями (1)
инициализируются во время статической инициализации. Эти инициализации включают
- Нулевая инициализация всех объектов со статической продолжительностью хранения
- Инициализация POD, инициализированных константными выражениями
Из ваших показанных переменных только cMyConstDouble
удовлетворяет обоим условиям полной инициализации во время статической инициализации. Однако cMyConstDouble2
этого не делает, поскольку его инициализатор не удовлетворяет требованиям константного выражения. В частности, он включает переменную, которая не имеет целочисленного типа (здесь она имеет тип с плавающей запятой). Однако с плавающей точкой литералы допускаются в арифметических константных выражениях. Вот почему 2.5*3.14
является арифметическим константным выражением. И именно поэтому изменение инициализатора на это потребует его статической инициализации.
Что будет с cMyConstDouble2
, если вы останетесь с непостоянным выражением? Ответ: ты не знаешь. Стандарт допускает статическую инициализацию этой переменной, но не требует этого. В вашем случае он был динамически инициализирован - таким образом, его значение сразу после статической инициализации все еще было равно нулю. Чтобы понять, насколько сложен , сложен , вот пример:
inline double fd() { return 1.0; }
extern double d1;
double d2 = d1; // unspecified:
// may be statically initialized to 0.0 or
// dynamically initialized to 1.0
double d1 = fd(); // may be initialized statically to 1.0
Если динамическая инициализация не изменяет никакую другую статическую переменную хранения (удовлетворяется в вашем коде) и когда статическая инициализация выдаст то же значение, что и динамическая инициализация, когда все объекты не требуются статическая инициализация будет динамически инициализироваться (также выполняется в вашем коде) - тогда переменная может быть инициализирована статически. Эти два условия также выполняются в приведенном выше коде для обеих переменных d2
и d1
:
Анализ d2
= d1
не меняет никакой другой статической переменной хранения
- Когда оба
d2
и d1
инициализируются динамически, тогда d2
будет инициализироваться равным 0.0
, потому что d2
определен до d1
, а динамическая инициализация d2
будет захватывать значение d1
как состояние сразу после статической инициализации (где имела место только нулевая инициализация d1
).
Анализ d1
= fd()
не меняет никакой другой статической переменной хранения
- Когда
d2
и d1
инициализируются динамически, тогда = fd()
инициализирует d1
до 1.0
.
Таким образом, компилятор может инициализировать d1
статически 1.0
, потому что оба условия для необязательной статической инициализации выполнены.
Если компилятор решит инициализировать d1
и d2
динамически, то d2
будет инициализирован до 0.0
, так как он захватит значение d1
как было сразу после нулевой инициализации.
Однако , , если компилятор решит инициализировать d1
статически и d2
динамически, тогда d2
будет инициализирован до 1.0
, поскольку динамическая инициализация d2
будет захватывать полностью инициализированное значение d1
, как это было сразу после статической инициализации.
Я не уверен, каково значение d2
, когда d1
и d2
статически инициализируются, однако. То есть, предполагается ли d2
захватить 0.0
или 1.0
, поскольку для статической инициализации не определен порядок.
(1) Выражения констант также включают выражения арифметических констант (не только целочисленные выражения констант) при рассмотрении порядка инициализации объектов со статической продолжительностью хранения.