В C ++ вызывает ли инициализация ссылки или указателя с самим собой UB?

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

См. также:  Как вы вызываете несколько файлов из командной строки в свое приложение?
Понравилась статья? Поделиться с друзьями:
IT Шеф
Комментарии: 2
  1. Dan
    // namespace scope
    int *p1 = p1; // p1 0 initialized, `p1` is a null ptr, not UB?
    

    Стандарт неоднозначен в отношении этого случая, но не может быть аргументировано возражение против UB из-за статической инициализации, которая предшествует динамической инициализации. С другой стороны, стандарт подразумевает, что время жизни объекта еще не началось.

    Подробнее о двусмысленности здесь: Если глобальная переменная инициализируется дважды (статически, а затем динамически), при какой инициализации начинается ее время жизни?

    // block scope
    int *p2 = p2; // pointer to garbage location. has UB ?
    

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

    // block scope
    int *p3 = p2; // Also has UB ?
    

    При инициализации p2 поведение уже не определено. Но предположим, что p2 было неопределенным значением без предыдущего UB:

    int *p2;
    int *p3 = p2;
    

    Поведение этого примера также не определено.

    Обратите внимание, что они не имеют ничего общего с объектом, являющимся указателем. Это относится к объектам почти всех типов.


    Ссылка должна быть инициализирована для ссылки на допустимый объект или функцию. Отсюда все три из них:

    // namespace scope
    int &r1 = r1; // r1 0 initialized, `r1` references 0, not UB?
    
    // block scope
    int &r2 = r2; // reference to intermediate value. has UB ?
    int &r3 = r2; // Also has UB ?
    

    сделать программу некорректной.

    Я получаю предупреждение для локальной переменной, но не для глобальной.

    Я считаю, что компилятор не выполняет диагностику r1. Clang при необходимости диагностирует это. Кроме того, UB-sanitizer clang обнаруживает его во время выполнения.

    А как насчет ссылок? Есть int &a = a; УБ. Я получаю предупреждение для локальной переменной, но не для глобальной. person Dan; 15.06.2021

    int 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

  2. Dan

    В случае глобальных указателей неинициализированные глобальные переменные всегда инициализируются значением «0».

    Локальные указатели, как вы заметили, указывают на какой-то нежелательный адрес, если он не инициализирован.

    Ссылки (локальные или глобальные) всегда должны инициализироваться переменной, что означает, что ссылка привязана к переменной, которой мы инициализируем. Но если вы ссылаетесь на то же самое, то это неопределенное поведение. В моем случае он создает дамп ядра, когда я пытаюсь распечатать значение ссылки.

    Я не думаю, что вопрос заключается в том, используется ли значение UB, но только если инициализация — UB. person Dan; 15.06.2021

Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: