Подтвердить что ты не робот

NULL перед удалением объекта с перегруженным удалением

Это стало одним из комментариев к обзору кода.

Хорошо ли проверять NULL перед вызовом delete для любого объекта?

Я понимаю, что оператор delete проверяет для NULL внутренне и является избыточным, но аргумент, который был указан, был удалён, поскольку оператор может быть перегружен, и если перегруженная версия не проверяет NULL, она может быть повреждена. Так безопасно и разумно предположить, что если и когда удаление будет перегружено, он будет проверять NULL или нет? В моем понимании разумно предположить, что первый случай, когда перегруженный delete должен позаботиться о проверке NULL, и точка обзора не устраивает. Как вы думаете?

4b9b3361

Ответ 1

Нет, не проверяйте значение null. В стандарте указано, что delete (T*)0; действителен. Это просто усложнит ваш код без каких-либо преимуществ. Если operator delete перегружено, лучше проверить значение null в реализации оператора. Просто сохраняет строки кода и ошибки.

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

Стандарт фактически говорит в [basic.stc.dynamic], по крайней мере, с С++ 03:

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

В тех случаях, когда ссылочные разделы, а также некоторые другие места в стандарте, перечисленные в других ответах, говорят, что семантика передачи нулевого указателя является no-op.

Ответ 2

Я бы сказал, что это еще одна причина для того, чтобы, если вы перегрузили operator delete, тогда вы всегда должны проверить его на NULL, иначе вы нарушаете семантику.

Ответ 3

Хорошо ли проверить NULL перед вызовом delete для любого объекта?

Нет!

int *p = NULL;
delete p ; //no effect

В стандарте говорится [Раздел 5.3.5/2]

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

Кроме того, в разделе 18.4.1.1/13

void operator delete(void* ptr) throw();

void operator delete(void* ptr, const std::nothrow_t&) throw();

Поведение по умолчанию:

- Для нулевого значения ptr ничего не делать.

- Любое другое значение ptr должно быть значением, возвращенным ранее вызовом оператора по умолчанию new, который не был аннулирован промежуточным вызовом оператора delete (void *) (17.4.3.7). Для такого ненулевого значения ptr восстанавливает хранилище, выделенное более ранним вызовом для нового оператора по умолчанию.

ИЗМЕНИТЬ:

Джеймс Канзе здесь говорит, что

По-прежнему сохраняется вероятность удаления оператора (или удаления []) для проверки; стандарт не гарантирует, что ему не будет присвоен нулевой указатель; стандарт требует, чтобы он был не-op, если был задан нулевой указатель. Или, что реализация разрешена для вызова. Согласно последнему проекту: "Значение первого аргумента, переданного функции дезадаптации, может быть значением нулевого указателя, и если функция освобождения включена в стандартную библиотеку, вызов не имеет никакого эффекта". Я не совсем уверен, что последствия того, что "есть тот, который поставляется в стандартной библиотеке", должны быть приняты буквально, поскольку его функция не входит в стандартную библиотеку, предложение, похоже, не будет применяться, Но почему-то это не имеет смысла.

Ответ 4

Я бы сказал, что ответственность за перегрузку delete лежит в том, как вы ожидаете, что delete будет вести себя. То есть, он должен обрабатывать указатели NULL как нет-op.

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

Ответ 5

Нет необходимости проверять значение null. оператор delete делает chck для null, поэтому дополнительная проверка не требуется.

Ответ 6

delete (T*)0; действителен и ничего не делает, аналогично free(NULL); также действителен и ничего не делает. Если вы перегрузите оператор delete, ваша реализация должна нести ту же семантику. В стандарте указано, как будет работать стандартный delete, но я не думаю, что он говорит о том, как должен себя вести перегруженный delete. Для согласованности со стандартным/стандартным поведением он должен позволить (T*)0 в качестве ввода.

Ответ 7

Из стандартных документов, 18.5.1.1.13 в разделе delete,

Поведение по умолчанию: Если значение ptr равно null, ничего не делает. В противном случае восстанавливает хранилище, выделенное предыдущим вызовом оператора new.

Итак, вам не нужно проверять по умолчанию.

Ответ 8

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

Однако для того, что стоит, вы всегда должны помнить, чтобы назначить ноль любому указателю, который вы только что удалили, если, например, вы также не захотите удалить указатель:

void MyObj::reset()
{
    delete impl_;
    impl_ = 0;    // Needed here - impl_ may be reused / referenced.
}

MyObj::~MyObj()
{
    delete impl_; // No need to assign here as impl_ is going out of scope.
}

Ответ 9

Требуется ли не проверить. Если кто-то перегружает этот пост, то это его ответственность за то, что с NULL.

Ответ 10

Я бы сказал, что вопросы содержат неполную информацию. Мой магазин все еще имеет чек на NULL, прежде чем удалить в нашем стандарте кодирования, так как у нас еще один компилятор конфигурация/платформы, что мы должны поддерживать, что переходит в поведение undefined с DEFUALT удалить оператор, если он передается NULL. Если исходный плакат имеет симуляционную ситуацию, тогда есть точка для проверки для NULL, иначе измените стандарт кодирования!

Ответ 11

Немного педантичности С++: NULL не является встроенной концепцией. Да, мы все знаем, что это значит, но в С++ до С++ 0X понятие null-указателя - это просто значение 0. NULL обычно представляет собой специфичный для платформы макрос, который расширяется до 0.

С С++ 0X мы получаем nullptr, который является более четким, чем простой ноль, и не конвертируется ни в один целочисленный тип, кроме bool, и является более понятной концепцией, чем NULL (или, возможно, лучшей реализацией концепции за NULL).