int &r1 = r1; // r1 0 initialized, `r1` references 0, not UB?
int *p1 = p1; // p1 0 initialized, `p1` is a null ptr, not UB?
int main() {
int &r2 = r2; // reference to intermediate value. has UB ?
int &r3 = r2; // Also has UB ?
int *p2 = p2; // pointer to garbage location. has UB ?
int *p3 = p2; // Also has UB ?
return 0;
}
Оценка неинициализированного указателя вызывает неопределенное поведение: Где именно стандарт C ++ говорит, что разыменование неинициализированного указателя является неопределенным поведением?
Но оцениваются ли указанные выше указатели / ссылки?
В этом вопросе я хотел спросить о следующих случаях:
- Назначение ссылки на себя в области видимости файла и области блока.
- Назначение указателя самому себе в области видимости файла и области блока.
- Назначение неинициализированной ссылки другой ссылке.
- Назначение неинициализированного указателя другому указателю.
Он компилируется? — person Dan schedule 15.06.2021
Да, но может выдавать предупреждения, как и ожидалось. — person Dan schedule 15.06.2021
Я получаю интересный результат для эталонной самоинициализации в области пространства имен — live — godbolt.org/z/W84nW5GYY Все компиляторы обнаруживают это, если объявление является локальным. — person Dan schedule 15.06.2021
Что вы пытаетесь достичь? Это просто упражнение в непонятных причудах C ++? — person Dan schedule 15.06.2021
@KamilCuk извините за опечатку, она исправлена. — person Dan schedule 15.06.2021
Применима ли такая причуда только к указателям и ссылкам? Например, я не думаю, что int a = a;
разрешено. — person Dan schedule 15.06.2021
@tobias разрешено. подробнее об этом: stackoverflow.com/questions/67979228/ — person Dan schedule 15.06.2021
@Dan Разрешенный ответ относится только к int i = i;
, а не int a = a;
, который находится в другом контексте. Разница в продолжительности хранения. В этом отношении нет разницы между int и указателем. — person Dan schedule 15.06.2021
Стандарт неоднозначен в отношении этого случая, но не может быть аргументировано возражение против UB из-за статической инициализации, которая предшествует динамической инициализации. С другой стороны, стандарт подразумевает, что время жизни объекта еще не началось.
Подробнее о двусмысленности здесь: Если глобальная переменная инициализируется дважды (статически, а затем динамически), при какой инициализации начинается ее время жизни?
да. В отличие от продолжительности статического хранения, автоматический объект не имеет стадии статической инициализации и имеет неопределенное значение перед инициализацией. Вы используете это неопределенное значение для инициализации, и поведение программы однозначно не определено.
При инициализации
p2
поведение уже не определено. Но предположим, чтоp2
было неопределенным значением без предыдущего UB:Поведение этого примера также не определено.
Обратите внимание, что они не имеют ничего общего с объектом, являющимся указателем. Это относится к объектам почти всех типов.
Ссылка должна быть инициализирована для ссылки на допустимый объект или функцию. Отсюда все три из них:
сделать программу некорректной.
Я считаю, что компилятор не выполняет диагностику
r1
. Clang при необходимости диагностирует это. Кроме того, UB-sanitizer clang обнаруживает его во время выполнения.А как насчет ссылок? Есть
int &a = a;
УБ. Я получаю предупреждение для локальной переменной, но не для глобальной. — person Dan; 15.06.2021int i = i;
в глобальной области, похоже, не имеет UB в соответствии с этим: stackoverflow.com/questions/67979228/, будет ли то же самое не относиться к глобальным ссылкам и указателям? — person Dan; 15.06.2021@Dan То же самое относится к указателям, согласно моему ответу. Обратите внимание, что, похоже, у UB нет несколько двусмысленностей. Насчет ссылок я не уверен. — person Dan; 15.06.2021
@Dan Я расширил ответ на ссылки. — person Dan; 15.06.2021
@eerorika Я согласен с последним редактированием, ссылки должны быть инициализированы, но это похоже на лазейку. Означает ли
ill-formed
в данном случае UB с момента его компиляции? — person Dan; 15.06.2021@Dan плохо сформирован, по сути, то же самое, что и UB, в том, что касается гарантий времени выполнения. — person Dan; 15.06.2021
В случае глобальных указателей неинициализированные глобальные переменные всегда инициализируются значением «0».
Локальные указатели, как вы заметили, указывают на какой-то нежелательный адрес, если он не инициализирован.
Ссылки (локальные или глобальные) всегда должны инициализироваться переменной, что означает, что ссылка привязана к переменной, которой мы инициализируем. Но если вы ссылаетесь на то же самое, то это неопределенное поведение. В моем случае он создает дамп ядра, когда я пытаюсь распечатать значение ссылки.
Я не думаю, что вопрос заключается в том, используется ли значение UB, но только если инициализация — UB. — person Dan; 15.06.2021