10月04, 2008

构造函数中抛出异常会发生什么?

曾有人问了我个问题:如果在构造函数中抛出异常会怎么样?

现在可以回答了。

构造函数中抛出异常的主要问题是:当有多个资源分配时,如果出现异常,如何释放已经成功分配的资源。

下面是TCPL中推荐的一种方法:基本思想是将资源封装在对象中,然后将该对象以成员变量的形式聚合入你的类中。这个封装类在其析构函数中释放资源。这样,当你的类的构造函数中出现异常后,编译器会调用封装类的对象的析构函数,释放资源。

#include <iostream>
using namespace std;
template <class T>
void* ch_malloc(bool succ, char* name) {
  cout << name << ":" << endl;
  if (succ)
    return malloc(sizeof(T));
  else {
    throw(exception("Memory Allocation Failed!"));
  }
  return 0;
}

class ch_File {
 private:
  void* data;

 public:
  ch_File(void* p) { data = p; }
  ~ch_File() {
    cout << "=>ch_File::~ch_File()" << endl;
    cout << " data:" << data << endl;
    delete data;  //释放资源
  }
};

class Klass {
 private:
  ch_File p1;
  void* p2, *p3;

 public:
  Klass()
      : p1(ch_malloc<char>(true, "p1")),
        p2(ch_malloc<char>(false, "p2")),  // <-- 调用p1的析构函数
        p3(ch_malloc<char>(true, "p3")) {
    // will not reach here
    cout << "=>Klass::Klass" << endl;
  }
};

int main(int argc, char* argv[]) {
  try {
    Klass k;
  } catch (exception e) {
    cout << e.what() << endl;
  }
  return 0;
}

输出

p1:
p2:
=>ch_File::~ch_File()
data:00386580
Memory Allocation Failed!

第二种方法:

在构造函数中使用 function-try-block,如下代码所示。

这种方法比较简洁,不用将所有资源封装,也不一定要用auto_ptr。

但是并不是所有的编译器都支持 function-try-block,比如vc6。vc9和g++都支持。vc7,vc8没有验证。

#include <iostream>
using namespace std;
template <class T>
void* ch_malloc(bool succ, char* name) {
  cout << "allocating " << name << endl;
  if (succ)
    return malloc(sizeof(T));
  else {
    throw(exception("Memory Allocation Failed!"));
  }
  return 0;
}

class Klass {
 private:
  void* p1, *p2, *p3;

 public:
  Klass() try : p1(0), p2(0), p3(0) {
    p1 = ch_malloc<char>(true, "p1");
    p2 = ch_malloc<char>(false, "p2");
    p3 = ch_malloc<char>(true, "p3");
  } catch (...) {
    cout << "=>ctor-try-block";
    delete this;  // compiler will insert a "throw" here
  }
  ~Klass() {
    cout << "=>Klass::~Klass()" << endl;
    cout << " p1:" << p1 << endl;
    cout << " p2:" << p2 << endl;
    cout << " p3:" << p3 << endl;
    delete p1;
    delete p2;
    delete p3;
  }
};
int main(int argc, char* argv[]) {
  try {
    Klass k;
  } catch (exception e) {
    cout << e.what() << endl;
  }
  return 0;
}

输出

allocating p1
allocating p2
=>ctor-try-block=>Klass::~Klass()
p1:00375FC8
p2:00000000
p3:00000000
Memory Allocation Failed!

本文链接:http://aztack.wang/post/what-if-exception-occurs-in-ctor-in-cpp.html

-- EOF--

Comments

评论加载中...

注:如果长时间无法加载,请针对 disq.us | disquscdn.com | disqus.com 启用代理。