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

Почему "оператор delete" вызывается, когда я вызываю "delete" на нулевом указателе?

При чтении ответов на этот вопрос я заметил, что ответы (this) подразумевают, что operator delete можно вызывать, даже если оператор delete выполняется с нулевым указателем.

Итак, я написал небольшой фрагмент:

class Test {
public:
    void* operator new( size_t ) { /*doesn't matter*/ return 0; }
    void operator delete( void* ptr ) {
        ptr; //to suppress warning and have a line to put breakpoint on
    }
};

int main()
{
    Test* ptr = 0;
    delete ptr;
}

и - неожиданно для меня - Test::operator delete() вызывается с ptr с нулевым указателем.

Как я понимаю, operator new выделяет память, а operator delete возвращает память в распределитель. Если я вызываю оператор delete на нулевом указателе, это означает, что за указателем не было объекта и нет памяти для возврата в распределитель.

Оператор

delete включает вызов деструктора. Когда я передаю нулевой указатель, деструктор, безусловно, не вызывается - С++ позаботится об этом. Тогда почему в этом случае вызывается operator delete?

4b9b3361

Ответ 1

Язык в следующем стандарте С++ 0x (раздел 5.3.5 [expr.delete]) выглядит следующим образом:

Если значение операнда выражение delete не является нулевым значение указателя, выражение-выражение вызовет функцию освобождения (3.7.4.2). В противном случае не указано, будет ли освобождение функция будет вызвана. [ Обратите внимание функция освобождения называется независимо от того, является ли деструктор для объекта или какого-либо элемента array генерирует исключение. - конечная нота]

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

EDIT: термин функция освобождения, используемая стандартом, как представляется, вызывает некоторую путаницу. Он поставляется со ссылкой. Некоторые ключевые слова из 3.7.4.2 [basic.stc.dynamic.deallocation], которые могут помочь уточнить:

Если класс T имеет функцию освобождения члена с именем operator deleteс точно одним параметром, то эта функция является обычной функцией (без размещения) освобождения.

В стандарте также очень ясно, что пользовательский operator delete должен принимать параметр, который является значением нулевого указателя:

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

Но из-за неуказанного поведения 5.3.5 вы не должны полагаться на вызов operator delete, когда указатель имеет значение null.

Ответ 2

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

Это похоже на вопрос, почему operator+ вызывается при добавлении 0.