为什么我们需要一个函数try块?

时间:2014-05-20 07:45:58

标签: c++ c++11 exception-handling try-catch

这是post的后续问题。有关“function try block”的定义,请参阅此问题的结尾。

问题:如果函数try块没有“处理”构造函数中引发的异常,为什么我们需要它们呢?你能举一个利用函数try块的例子吗?

考虑以下代码。

#include <iostream>
#include <new>  
#include <exception>
using namespace std;

struct X {
  int *p;
  X() try : p(new int[10000000000]) {}
  catch (bad_alloc &e) {
    cerr << "exception caught in the constructor: " << e.what() << endl;
  }
};

int main() {
  try {
    X x;
  }
  catch (exception &e){
    cerr << "exception caught outside the constructor: " << e.what() << endl;
  }
  return 0;
}

输出

exception caught in the constructor: std::bad_alloc exception caught outside the constructor: std::bad_alloc

在我看来,无论我在函数try块中做什么,异常总是被抛到调用构造函数的外部作用域,例如:上面代码中的X x;

“function try block”的定义,摘自“C ++ Primer 5th。”

  

要从构造函数初始化程序处理异常,我们必须将构造函数编写为函数try块。函数try块允许我们将一组catch子句与构造函数的初始化阶段(或析构函数的销毁阶段)以及构造函数(或析构函数)函数体相关联。

2 个答案:

答案 0 :(得分:3)

你是对的,总是传播异常。

函数try块使您能够捕获该异常,例如销毁作为参数传递的对象(也许这是一个智能指针类?),而不引入人工基类。

更一般地说,它使您能够清除函数调用引入的状态更改。


对于构造函数的情况:

异常传播析构函数为所有成功构造的子对象调用,包括基类子对象(如果有的话)。

但是,这个没有完全构造的对象自己的析构函数不会被调用。函数try块理想情况下不是用于处理析构函数的设备。未完全创建的对象自己的析构函数无关,因为它的任务是清理由构造函数体和/或后来的成员函数调用引入的状态更改,并且使用常见的“零规则”设计,没有这样的爱好。

答案 1 :(得分:2)

当构造函数抛出时,相应的析构函数不会运行。这就是你书中引用的原因:清理必须由构造函数本身完成。

但是您的示例显示异常传播。这是必要的,因为构造函数失败,因此没有创建对象。调用代码不应该像构造函数创建一个对象那样继续。

相关问题