Безопасно ли удалить nullptr в с ++ 0x?

85

В c++03ней довольно ясно , что удаление пустого указателя не имеет никакого эффекта. В самом деле, это прямо указано в §5.3.5/2том, что:

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

Тем не менее, в текущем проекте для c++0xэтого предложения , кажется, отсутствует. В остальной части черновика я смог найти только предложения, в которых говорится, что произойдет, если операнд выражения удаления не является константой нулевого указателя. Удаление нулевого указателя все еще определено в c++0x, и если да, то где?

Ноты:

Существуют значительные косвенные доказательства, позволяющие предположить, что это понятие все еще хорошо определено.

Во-первых, есть два предложения, в которых §5.3.5/2говорится, что

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

и

Во втором варианте (массив удаления) значение операнда удаления может быть значением нулевого указателя или ...

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

Во-вторых, изменение значения delete 0- это серьезное изменение, и комитет по стандартам вряд ли внесет это конкретное изменение. Кроме того, нет упоминания о том, что это критическое изменение в Приложении по совместимости (Приложение C) c++0xпроекта. Приложение C, однако, является информативным разделом, поэтому оно не имеет отношения к интерпретации стандарта.

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

Mankarse
источник

Ответы:

102

5.3.5 / 7 говорит:

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

И 3.7.4.2/3 говорит:

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

Таким образом, поведение четко определено, если используется стандартная функция освобождения или предоставленная пользователем функция освобождения правильно обрабатывает нулевые указатели.

интерджей
источник
9
Начиная с C ++ 14: «Если выражение оценивается как значение нулевого указателя, деструкторы не вызываются и функция освобождения не вызывается».
Вормер
2
@Wormer Я не думаю, что эта страница правильная. Стандарт C ++ 14 по-прежнему говорит, что «не определено, будет ли вызываться функция освобождения памяти», когда указатель равен нулю (5.3.5 / 7).
Interjay
1
Как и в стороне, это не безопасно вызывать fclose () для указателя пустого файла. В Ubuntu (и, возможно, в других операционных системах) fclose (NULL) вызывает ошибку сегментации.
Джерри Борегар
7

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

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

Также примечательно: старый стандарт противоречил сам себе тем, что в нем говорилось (5.3.5 / 2), что «если значение операнда удаления является нулевым указателем, операция не имеет эффекта», но позже сказал, что (5.3.5 / 7) «выражение-удаление вызовет функцию освобождения». Вызов функции - это эффект. Это особенно верно, поскольку вызываемая функция вполне может быть переопределенной operator delete.

Новая формулировка устраняет это противоречие, явно оставляя на усмотрение реализации вопрос о том, вызывается ли функция освобождения в случае удаления нулевого указателя.

Дэвид Хаммен
источник