Это
int main() {
int foo = foo;
}
Объект foo
существует после =
, согласно [basic.scope.pdecl]
:
Точкой декларации для имени является сразу после его полного декларатора (пункт 8) и перед его инициализатором (если есть).
Однако программа в целом не определена, поскольку вы используете (в RHS) неинициализированное значение:
int x = x;
Здесь [..] x
инициализируется своим собственным (неопределенным) значением.
И
Несмотря на то, что стандарт "подразумевает и неправильно определяет", и преобразование lvalue в rvalue выполняется для выражения RHS foo
.
А ([conv.lval]
):
lvalue (3.10) не функции,
не массив типа T может быть преобразован в
значение. Если T является неполным типом,
программа, которая требует этого
обращение плохо сформировано. Если
Объект, на который ссылается lvalue,
не является объектом типа T и не является
объект типа, производного от T, или , если
объект неинициализирован, программа
что требует этого преобразования имеет
неопределенное поведение.
При правильном уровне предупреждения вам сообщат об этом ; однако, программы, вызывающие неопределенное поведение, могут компилироваться. Они просто могут делать что угодно, когда вы их запускаете.
Или как насчет этого?
int foo = foo;
int main() {}
Обратите внимание, что foo
является «глобальным». Они инициализируются нулями в качестве первого шага, согласно [basic.start.init]
:
Объекты со статической продолжительностью хранения (3.7.1) должны быть инициализированы нулями (8.5) до того, как произойдет любая другая инициализация .
Таким образом, вы получите int foo
со значением 0; на данный момент оно действительно, согласно [basic.scope.pdecl]
выше и [stmt.decl]
:
Инициализация нуля (8.5) всех
локальные объекты со статическим хранилищем
Продолжительность (3.7.1) выполняется до
любая другая инициализация имеет место. [..]
Затем вы инициализируете значение foo
(само), т. Е. 0.
Это хорошо определено ... если немного загадочно.
В интересах тщательности, вот третий и последний случай:
int foo = 42;
int main() {
int foo = foo;
}
К сожалению, это то же самое, что и в первом случае . Поскольку локальный foo
уже объявлен и находится в области действия к моменту оценки инициализатора, инициализатор использует локальный foo
, и вы все еще застряли с неопределенным поведением. Глобальный foo
не используется.