Назначение ссылки путем разыменования пустого указателя - PullRequest
12 голосов
/ 16 июля 2011
int&  fun()
{
    int * temp = NULL;
    return *temp;
}

В приведенном выше методе я пытаюсь выполнить разыменование пустого указателя.Когда я вызываю эту функцию, она не дает исключения.Я обнаружил, что когда возвращаемый тип по ссылке, он не дает исключения, если он по значению, то он делает.Даже когда разыменование указателя NULL используется для ссылки (как в приведенной ниже строке), оно также не дает.

int* temp = NULL:
int& temp1 = *temp;

Здесь мой вопрос заключается в том, что компилятор не выполняет разыменование в случае ссылки?

Ответы [ 5 ]

16 голосов
/ 16 июля 2011

Разыменование нулевого указателя: Неопределенное поведение .

Неопределенное поведение означает, что все может произойти, поэтому невозможно определить поведение для этого.

По общему признанию, я собираюсь добавить эту стандартную цитату C ++ в n-й раз, но, кажется, это должно быть.

Относительно неопределенного поведения,

C ++ Стандартный раздел 1.3.24 гласит:

Допустимое неопределенное поведение варьируется от полного игнорирования ситуации с непредсказуемыми результатами до поведения во время перевода или выполнения программы документированным образом, характерным для среды (с выдачей или без выдачи диагностического сообщения), до завершения перевода или выполнения с выдачей диагностического сообщения).

Примечание:
Кроме того, просто чтобы сообщить об этом:
Использование возвращенной ссылки или указателя на локальную переменную внутри функции также является неопределенным поведением. Вы должны выделить указатель на freestore (кучу), используя new, а затем вернуть ссылку / указатель на него.

EDIT:
Как @James McNellis, правильно указывает в комментариях,
Если возвращенный указатель или ссылка не используется, поведение четко определено .

7 голосов
/ 16 июля 2011

Когда вы разыменовываете нулевой указатель, вы не обязательно получаете исключение;все, что гарантировано, это то, что поведение не определено (что на самом деле означает, что вообще нет никакой гарантии в отношении того, что такое поведение).

После вычисления выражения *temp невозможно рассуждать оПоведение программы.

4 голосов
/ 16 июля 2011

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

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

1 голос
/ 16 июля 2011

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

Некоторая история и информация нулевых указателей в семействе Algol / C: http://en.wikipedia.org/wiki/Pointer_(computing)#Null_pointer

Примеры и последствия неопределенного поведения: http://en.wikipedia.org/wiki/Undefined_behavior#Examples_in_C

0 голосов
/ 16 июля 2011

Я не уверен, что понимаю, что вы пытаетесь сделать.Разыменование указателя ** NULL ** не определено.

Если вы хотите указать, что ваш метод не всегда возвращает значение, вы можете объявить его как:

bool fun (int & val);

или stl way (аналогично std :: map insert):

std::pair<int, bool> fun();

или boost:

boost::optional<int> fun();
...