Являются ли ссылки на 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.