Почему «оператор delete» вызывается, когда я вызываю «delete» для нулевого указателя? - PullRequest
17 голосов
/ 29 сентября 2010

При чтении ответов на на этот вопрос я заметил, что ответы (например, на этом ) подразумевают, что 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 оператор включает в себя вызов деструктора. Когда я передаю нулевой указатель, деструктор, безусловно, не вызывается - C ++ позаботится об этом. Тогда почему operator delete вызывается в этом случае?

Ответы [ 2 ]

19 голосов
/ 29 сентября 2010

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

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

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

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

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

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

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

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

9 голосов
/ 29 сентября 2010

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...