Являются ли ссылки nullptr на неопределенное поведение в С++?

Следующий код дурачится с указателем nullptr и ссылкой:

#include <cstdio>

void printRefAddr(int &ref) {
    printf("printAddr %p\n", &ref);
}

int main() {    
    int *ip = nullptr;
    int &ir = *ip;

    // 1. get address of nullptr reference
    printf("ip=%p &ir=%p\n", ip, &ir);

    // 2. dereference a nullptr pointer and pass it as reference
    printRefAddr(*ip);

    // 3. pass nullptr reference
    printRefAddr(ir);

    return 0;
}

Вопрос. Являются ли в стандартах C++ закомментированные операторы 1..3 действительным кодом или неопределенным поведением?

Является ли это одинаковым или разным для разных версий С++ (в более старых версиях, конечно, будет использоваться литерал 0 вместо ключевого слова nullptr)?

Дополнительный вопрос: существуют ли известные варианты компиляторов/оптимизации, которые на самом деле могут привести к тому, что приведенный выше код сделает что-то неожиданное/сбой? Например, есть ли флаг для любого компилятора, который будет генерировать неявное утверждение для nullptr везде, где инициализируется ссылка, включая передачу аргумента ссылки из *ptr?


Пример вывода для любопытных, ничего неожиданного:

ip=(nil) &ir=(nil)
printAddr (nil)
printAddr (nil)

person hyde    schedule 23.04.2013    source источник
comment
ссылки нулевого указателя всегда были UB. ты искал?   -  person sehe    schedule 23.04.2013
comment
Вы получаете UB задолго до (1) уже, когда вы разыменовываете ip в первый раз.   -  person Xeo    schedule 23.04.2013


Ответы (2)


// 2. dereference a nullptr pointer and pass it as reference

Разыменование нулевого указателя является неопределенным поведением, поэтому независимо от того, передаете ли вы его как ссылку или по значению, факт заключается в том, что вы разыменовали его и, следовательно, вызвали UB, что означает, что с этого момента все ставки выключенный.

Вы уже вызывали UB здесь:

int &ir = *ip; //ip is null, you cannot deref it without invoking UB.
person Tony The Lion    schedule 23.04.2013

Поскольку ir — это всего лишь тень *ip, она сама по себе не вызовет неопределенного поведения.

Неопределенное поведение использует указатель, указывающий на nullptr_t. Я имею в виду использование *ip. Поэтому

int &ir = *ip;
          ^^^

Вызывает УБ.

person masoud    schedule 23.04.2013