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

Следующий код дурачится с 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 являются допустимым кодом или неопределенным поведением?

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

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


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

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

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.

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

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

int &ir = *ip;
          ^^^

Вызывает UB.

Другие вопросы по тегам