当我在空指针上调用"delete"时,为什么会调用"operator delete"?

sha*_*oth 17 c++ pointers memory-management

在阅读这个问题的答案时,我注意到答案(例如这个)意味着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;
}
Run Code Online (Sandbox Code Playgroud)

并且 - 令我惊讶的是 - Test::operator delete()通过ptr持有空指针来调用.

据我所知,它operator new分配内存operator delete并将内存返回给分配器.如果我delete在空指针上调用语句,则意味着指针后面没有对象,并且没有内存返回到分配器.

delete语句包括调用析构函数.当我传递一个空指针时,肯定不会调用析构函数--C++会处理这个问题.那么为什么operator delete在这种情况下被调用?

Ben*_*igt 19

即将推出的C++ 0x标准(第5.3.5节[expr.delete])中的语言如下:

如果delete-expression的操作数的值不是空指针值,则delete-expression将调用释放函数(3.7.4.2).否则,未指定是否将调用释放功能.[注意:无论对象的析构函数或数组的某个元素是否引发异常,都会调用释放函数. - 结束说明]

所以它是未指定的行为,一些编译器可能会operator delete在删除NULL指针时调用,而其他编译器可能不会.

编辑:标准使用的术语解除分配功能似乎引起了一些混乱.它附带一个参考.3.7.4.2中的一些关键语言[basic.stc.dynamic.deallocation]可能有助于澄清:

如果一个类T具有operator delete 仅使用一个参数命名的成员释放函数,则该函数是通常的(非放置)释放函数.

标准也很清楚,用户定义的operator delete需要接受一个空指针值的参数:

提供给解除分配函数的第一个参数的值可以是空指针值; 如果是这样,并且如果解除分配功能是标准库中提供的功能,则该调用无效.

但是由于5.3.5的未指定行为,operator delete当指针为空时,不应该依赖于被调用.


Tyl*_*nry 9

运算符删除就像任何其他运算符一样,为什么不调用它?它调用之前无法检查其参数.

这就像operator+在你添加0时询问为什么被调用.

  • `delete`语句不仅调用`operator delete`,它首先调用析构函数,并且在调用析构函数之前必须进行空检查(因此在调用`operator delete`之前).`operator delete`与其他运算符重载不同. (11认同)
  • 实际上,C++标准明确允许编译器避免使用空指针值调用`operator delete`. (4认同)
  • 同意Ben Voigt:当你输入`delete p;`时,编译器首先调用对象的析构函数,然后调用deallocation函数`operator delete`.系统必须能够诊断指针为0,以避免调用析构函数(它不会调用它),所以从技术上讲它也可以避免调用deallocator. (2认同)