глобальная переменная инициализируется дважды? - PullRequest
0 голосов
/ 17 февраля 2012

file1.cpp

#include <iostream>

extern int u;
int i=9;
int j=i+9;
int main()
{
   std::cout<<u;
   return 0;
}

file2.cpp

extern int j;
int u=j+9;

Результат равен u = 9, но не 27

Это показывает, что j инициализируется дважды - сначаланоль (из-за которого variable u получить значение 9), а затем с 18

Возможно ли это ??Мое значение для инициализации здесь разрушено.

Я также пытаюсь сделать variable j константой, чтобы увидеть, что будет дальше

file1.cpp // после изменения j на константу

extern int u;
int i=9;
extern const int j=i+9;

Это имеет тот же вывод, что и раньше.

Однако, если я изменю int j=i+9; (в file1.cpp) на int j=9;

Удивительно, но я получил правильные значения, то есть u = 18;

Ответы [ 4 ]

4 голосов
/ 17 февраля 2012

Порядок инициализации глобальных переменных объявляется для разных Единиц перевода не указан.

Глобальные переменные u и i, j находятся в разных единицах перевода в вашем коде, поэтому порядок инициализации u выполняется первым или i & j инициализируется до u не определено.
Это вызывает неопределенное поведение в вашем коде.
Это вызывает неопределенное поведение в вашем коде

Однако, обратите внимание, что порядок инициализации глобальных переменных водна и та же единица перевода четко определена.
, т. е. хорошо определено, что i будет инициализирован до j в вашем коде.

То, что вы видите, является классическим случаем Статическая инициализация Fiasco .

2 голосов
/ 17 февраля 2012

Поскольку "i" не является "const int", i + 9 не является константным выражением.Это делает так, чтобы инициализация "j" была динамической.Один из "ты" тоже.Порядок динамических инициализаций "u" и "j" не определен.Таким образом, вы не знаете, какое значение будет использоваться для «и».В вашем случае вы получите значение «j», которое было результатом нулевой инициализации, но до того, как оно было динамически инициализировано, поэтому «j» был по-прежнему нулевым.

Если вы сделаете «i» «const int»тогда вы должны получить правильное значение в «u», так как «j» будет статически инициализироваться.

1 голос
/ 17 февраля 2012

Это то, что согласно стандарту должно произойти.Все статические объекты инициализируются нулями, прежде чем что-либо еще происходит.Затем идет вся статическая инициализация, затем вся динамическая инициализация.Внутри единицы перевода инициализация происходит в лексическом порядке определений;между единицами трансляции порядок не указан, поэтому может ли изменяться (динамическая) инициализация u до или после динамической инициализации j;изменение порядка указания файлов в командной строке может изменить поведение вашего кода.

Если инициализация выполняется с помощью константного выражения, то она становится статической инициализацией.Чтобы выражение считалось константным выражением, все переменные в нем должны быть const, сами должны быть инициализированы с помощью константного выражения, и их инициализаторы должны быть видимыми.В вашем случае создание всех переменных const будет означать, что j имеет статическую инициализацию, но ничего не сделает для u, потому что инициализатор для j не виден в file2.cpp.

1 голос
/ 17 февраля 2012

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...