Подтвердить что ты не робот

Стандартная ссылка для int foo = foo

int foo = foo; компилируется. Какая часть стандарта С++ позволяет это?

4b9b3361

Ответ 1

3.3.1 Точка декларации [basic.scope.pdecl]

Точка объявления для имени сразу после его полного объявления (раздел 8) и перед его инициализатором (если есть),

Поведение хорошо определено, если декларация находится в области файлов. Если у вас есть объявление в области функций, и если вы используете foo позже [, который будет инициализирован некоторым неопределенным значением в этом случае], это будет undefined.

Ответ 2

Это?

int main() {
  int foo = foo;
}

Объект foo существует после =, согласно [basic.scope.pdecl]:

Точка объявления для имени сразу после его полного объявления (раздел 8) и перед его инициализатором (если есть).

Однако программа в целом undefined, потому что вы используете (на RHS) неинициализированное значение:

int x = x;Здесь [..] x инициализируется собственным (неопределенным) значением.

и

Несмотря на то, что стандартное значение "выводится и плохо указано", преобразование lvalue-to-rvalue выполняется в выражении RHS foo.

И ([conv.lval]):

Значение (3.10) нефункции, тип без массива T может быть преобразован в rvalue. Если T - неполный тип, программа, которая требует этого преобразование плохо сформировано. Если объект, к которому относится значение lvalue не является объектом типа T и не является объект типа, полученного из T, или , если объект неинициализирован, программа что требует такого преобразования undefined.

С соответствующими уровнями предупреждения вам расскажут об этом; однако программам, вызывающим undefined Поведение, разрешается компилировать. Они просто могут что-то сделать, когда вы их запускаете.


Или, как насчет этого?

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, и вы все еще придерживаетесь поведения undefined. Глобальный foo не используется.