如果在构造函数抛出异常后释放分配的内存

时间:2014-03-03 01:49:15

标签: c++

我知道Object *pObject=new Object包含两个步骤:

  1. operator new to allocation memory
  2. 调用对象的构造函数。
  3. 并致电delete pObject

    1. 调用对象的破坏;
    2. operator delete to free memory。
    3. 但是当新的Object进程,如果第2步抛出异常,如果运算符delete被系统调用来释放内存?

2 个答案:

答案 0 :(得分:1)

不,不会调用析构函数。由于对象构造不正确,因此调用析构函数是不安全的。但是,如果任何成员对象已完全构造,则它们将被销毁(因为对象已完成)。

有些人建议不要抛弃构造函数,我相信它比僵尸状态更好,这类似于错误代码并且会产生冗长的代码。只要您遵循RAII,您应该没事(每个资源都由它自己的对象管理)。在你投入构造函数之前,请确保你清理了你已经完成了一半的任何事情,但是如果你使用的RAII应该是什么都没有。

以下输出“B”:

#include <iostream>

struct B {
  ~B() { std::cout << "B" << std::endl; }
};

struct A {
  A() : b() { throw(1); }
  ~A() { std::cout << "A" << std::endl; }
  B b;
};

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

修改: 以上不是你问的,是的,调用了删除操作符,http://www.cplusplus.com/reference/new/operator%20delete []说:

“这些释放函数由delete-expressions和new-expression调用,用于在破坏(或无法构造)具有动态存储持续时间的对象后释放内存。”

可以通过覆盖运算符delete来测试。

答案 1 :(得分:0)

是的,将调用operator delete来释放分配的内存。

以下程序可以证明:

#include <iostream>

using std::cout;
using std::endl;

class A { 
public:
    A() { cout << "A() at " << this << endl; throw 1; }
    ~A() { cout << "~A() at " << this << endl; }
};

int main(int argc, char *argv[]) {
    int N = 3;
    for (int i = 0; i < N; ++i) {
        try {
            new A;
        } catch (int a) {
            // pass
        }   
    }   
    return 0;
}

在我的系统上运行这个程序,我发现打印出的结果是这样的:

A() at 0x2170010
A() at 0x2170010
A() at 0x2170010

显然,析构函数不会被调用,因为没有

~A() at 0x2170010
打印出

行。

肯定会调用operator delete,因为这三个对象的地址完全相同。