删除一个NULL指针在写入析构函数时不会调用重载删除

s_i*_*bhu 16 c++ destructor memory-management

class Widget
{
    public:
        Widget() {
            cout<<"~Widget()"<<endl;
        }
        ~Widget() {
            cout<<"~Widget()"<<endl;
        }

    void* operator new(size_t sz) throw(bad_alloc) {
        cout<<"operator new"<<endl;
        throw bad_alloc();
    }

    void operator delete(void *v) {
        cout<<"operator delete"<<endl;
    }

};

int main() 
{
    Widget* w = 0;
    try {
        w = new Widget();
    }
    catch(bad_alloc) {
        cout<<"Out of Memory"<<endl;
    }

    delete w;
    getch();
    return 1;
}
Run Code Online (Sandbox Code Playgroud)

在此代码中,析构函数存在时delete w不会调用重载delete运算符.如果省略析构函数,delete则调用重载.为什么会这样?

输出~Widget()时的输出

operator new
Out of Memory

未写入Widget()时的输出

operator new
Out of Memory
运算符删除

Abh*_*hay 21

我记得在comp.lang.c ++.moderated之前的操作符删除类似的东西.我现在找不到,但答案说明了这样的事情......

不幸的是,当在相应类型的空指针上调用delete-expression时,语言规范不足以清楚控件是否应该进入重载的'operator delete',即使标准确实在null上表示delete-expression -pointer是一个无操作.

詹姆斯·观世具体说:

它仍然是操作员删除(或删除[])的响应性检查; 标准不保证不会给出空指针; 如果给出空指针,标准要求它是无操作.或者允许实现调用它.根据最新的草案,"提供给释放函数的第一个参数的值可能是空指针值;如果是,如果解除分配函数是标准库中提供的函数,则调用无效." 我不太确定"标准库中提供的那个"的含义是什么意思 - 从字面上看,因为他的功能不是标准库提供的,句子似乎不适用.但不知何故,这没有意义

我记得这个becoz我在某个时候有类似的问题,并在.txt文件中保留了答案.

更新1:

哦,我在这里找到.另请阅读此链接缺陷报告.所以,答案是未指定的.第5.3.5/7章.


Pav*_*aev 9

首先,这可以真正简化为delete (Widget*)0- 你的其他一切都main()没有必要重复这一点.

这是一个代码生成假象,因为1)用户定义operator delete必须能够处理NULL值,2)编译器尝试生成最佳代码.

首先让我们考虑不涉及用户定义的析构函数的情况.如果是这种情况,那么除了之外没有代码可以在实例上运行operator delete.在将控制转移到之前检查null是没有意义的operator delete,因为后者应该进行检查; 所以编译器只生成无条件调用operator delete(并且你看到后者打印一条消息).

现在第二种情况 - 析构函数已定义.这意味着你的delete语句实际上扩展为两个调用 - 析构函数,和operator delete.但是无法在空指针上安全地调用析构函数,因为它可能会尝试访问类字段(编译器可能会发现您的特定析构函数并没有真正执行它,所以使用null调用是安全的this,但看起来他们不会'在实践中烦恼).所以它在析构函数调用之前插入一个空检查.一旦检查已经存在,它也可以使用它跳过调用operator delete- 毕竟它无论如何都需要成为无操作,并且operator delete如果指针实际上它将在内部空间进行额外的无意义检查一片空白.

据我所知,ISO C++规范无论如何都无法保证这一点.这只是两个编译器在这里进行相同的优化.

  • 很好的解释!Imho,还有第三种情况:虚拟析构函数定义.如果指针为NULL,则无法在运行时找到此项.删除NULL指针的另一个原因是无法调用析构函数代码... (2认同)