【问题标题】:Calling of delete after construction throwing an exception构造后调用删除抛出异常
【发布时间】:2018-01-28 16:08:39
【问题描述】:

我正在阅读 Effective C++ 第 3 版,第 52 项“如果您编写位置新,则写入位置删除”。

我想知道如何让操作符delete在构造抛出异常后自动调用。

#include <iostream>
using namespace std;

class A {
    int i;
public:
    static void* operator new(std::size_t size) throw(std::bad_alloc) {
        return malloc(size);
    }
    static void operator delete(void* p) throw() {
        cout << "delete" << endl;
        free(p);
    }
    A() {
        throw exception();
    }
};

int main() {
    A* a = new A;
}

以上代码只输出:

terminate called after throwing an instance of 'std::exception'
  what():  std::exception
[1]    28476 abort      ./test_clion

【问题讨论】:

  • 如果分配内存失败,则无法释放它
  • Delete 在构造函数抛出时自动调用。顺便说一下,这个例子实际上并不是placement new,也不能直接调用placement delete。但是如果它是placement new,并且构造函数抛出了一个异常,编译器会调用它的placement delete,因此是你书中的建议。

标签: c++ exception constructor new-operator delete-operator


【解决方案1】:

参考:operator delete, operator delete[]

我应该在try {} 中写new。目前对异常知之甚少。

#include <iostream>
using namespace std;

class A {
    int i;
public:
    static void* operator new(std::size_t size) throw(std::bad_alloc) {
        return malloc(size);
    }
    static void operator delete(void* p) throw() {
        cout << "delete" << endl;
        free(p);
    }
    A() {
        throw exception();
    }
};

int main() {
    try {
        A* a = new A;
    } catch (const exception&) {

    }
}

还有输出:

delete

【讨论】:

  • 或者,简而言之,未捕获的异常与在顶层捕获的异常不同。
  • @Yakk C++ 太复杂了。实际上,我不知道为什么只有在newtry {} 时才调用删除?
  • 未捕获的异常会终止您的程序,不会发生堆栈展开。捕获的异常会导致堆栈展开,这是清理内存的地方。
  • 标准规定“如果没有找到匹配的处理程序,则调用函数std::terminate();在调用std::terminate()之前是否展开堆栈是实现定义的”。因此编译器可以选择先删除A,然后再找到catch,或者推迟任何删除,直到捕获到该异常。如果它永远不会被抓住......
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-07-18
  • 2013-04-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-04
  • 1970-01-01
相关资源
最近更新 更多