尝试所有或只需要什么?

时间:2010-01-31 20:28:47

标签: c++

什么是更好的编码实践:如果我必须有一个try / catch块,我应该将所有内容(每次初始化等)放在这个块中,还是只放置那些可能抛出的变量?这两种结构有什么区别吗?

例如:
具有:

struct A  {
    A();
    int a;
    int* b;
};    

以及稍后的.cpp:

A::A() {
    a = 5;
    try {
       b = new int;
    }
    catch(...){ 
    }
}

A:A()  {
   try {
     a = 5; //this time in try block
      b = new int;
   }
   catch(...) { 
   }
}

这两个结构之间有什么区别,或者这是否在某种程度上,如果我必须有一个try / catch块,我可能还要把所有东西放进去吗? 谢谢。

P.S。 为了上帝的缘故,这里的格式化让我非常疯狂!而且我知道我多次提到这一点,我不会生气。

6 个答案:

答案 0 :(得分:10)

我认为一个好的一般原则是让try块尽可能“缩小” - 不要放入你认为不会导致异常的东西。这样一来,如果你错了并且其中一个“不能引起异常”的部分实际上引起异常,你就不会意外地“吞下”这个令人惊讶的异常(毫无疑问)以不恰当的方式处理它,因为你的代码不会期望那个异常,而是其他种类。)

答案 1 :(得分:3)

在您的代码中,我不会在您指示的位置使用try块。内存分配错误实际上非常罕见,很难从中恢复。我可能会在main中捕获异常,记录错误并退出程序。

更广泛地说,在C ++中,你不应该包含每个可以抛出try块的函数。您应该使用众所周知的C ++惯用语(如RAII)来编写可以处理异常的代码。

答案 2 :(得分:2)

除了Alex和Neil的优点之外,狭窄的try块使代码更容易理解。未来的维护者将更容易了解正在发生的事情。

答案 3 :(得分:1)

@ Alex, 我不同意。您应该将程序的逻辑部分分组为尝试捕获,这些捕获应该失败或作为一个整体传递。如果某些内容失败,即使您没有预料到,您的代码应该是异常安全的,并且整个操作应该失败并且所有资源都应该自动释放。如果你让它们变窄,那么你最终会得到大量的尝试和捕获量。为什么不使用IF呢? (但首先不是例外点吗?避免大量的ifs?)
Parashift也同意我的意见。
http://www.parashift.com/c++-faq-lite/exceptions.html#faq-17.12
阅读17.12和17.13。

答案 4 :(得分:1)

另一种看待这种情况的方法是在try块中包含语句,当它们都需要成功或一起失败时。这样,catch块就可以作为代码中的一种事务功能。所以,你可以这样做:

// save current state
try {
  // a few statements
  // that each modify the state
} catch (e) {
  // rollback to original state
}

在您的示例中,分配给成员变量a会更改对象的状态,因此它应该位于try块内。

答案 5 :(得分:0)

在我的代码中,除了main()之外,我几乎没有抓到任何东西。如果你觉得自己需要catch块来清理,你就会做错事,需要好好看看RAII的习语。至于其他任何事情 - 只应在特殊情况下抛出异常,并且很难在异常时刻提出通用智能的东西。