为什么在析构函数中抛出异常时不会调用重载删除?

Duk*_*ing 9 c++ destructor exception delete-operator c++11

我已经写了下面的代码,重载newdelete运营商,并引发在析构函数的异常.

抛出异常时,为什么delete操作符中的代码没有执行(并且"再见"打印)?

如果不应该执行,(如何)释放内存?是其他delete运营商之一吗?是否会重载其中一个而导致执行相应的代码?或者内存根本没有被释放,因为破坏失败意味着它可能不应该是?

#include <iostream>
using namespace std;
class A
{
public:
    A() { }
    ~A() noexcept(false) { throw exception(); }
    void* operator new (std::size_t count)
    {
        cout << "hi" << endl;
        return ::operator new(count);
    }
    void operator delete (void* ptr)
    {
        cout << "bye" << endl;
        return ::operator delete(ptr);
    }
    // using these (with corresponding new's) don't seem to work either
    // void operator delete (void* ptr, const std::nothrow_t& tag);
    // void operator delete (void* ptr, void* place);
};

int main()
{
    A* a = new A();
    try
    {
        delete a;
    }
    catch(...)
    {
        cout << "eek" << endl;
    }
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

输出:

hi
eek
Run Code Online (Sandbox Code Playgroud)

现场演示.

我在看:

但是我无法找到答案,确切地说(1)析构函数中的异常(而不是构造函数)和(2)重载删除.

我不需要在析构函数中抛出异常的演讲是不好的做法 - 我只是碰到了类似的代码,我对这种行为感到好奇.


如果存在这样的引用,我希望得到标准或类似引用支持的答案.

Bia*_*sta 6

标准草案N4296 5.3.5,PAG 121说:

[expr.delete] [注意:无论对象的析构函数或数组的某个元素是否引发异常,都会调用释放函数. - 结束说明]

因此,operator delete析构函数抛出必须被称为无忧无虑.

但是,正如评论中所显示的那样,一些编译器没有正确地调用它operator delete.这可以作为bug编译器来解决.

Bug测试:

  • 当引用标准时,您应该给出与您引用的部分相关联的标记(在本例中为[expr.delete]),因为这些部分可以移动并重新编号.(这是N4659中第8.3.5节第7段). (2认同)