函数的try-catch语法之间的区别

iam*_*ind 43 c++ syntax try-catch function-try-block

我最近遇到了这个语法try-catchfor function.

struct A
{
  int a;

  A (int i) : a(i)  // normal syntax
  {
    try {}
    catch(...) {}
  }

  A ()   // something different
  try : a(0) {}
  catch(...) {}

  void foo ()  // normal function
  try {}
  catch(...) {}
};
Run Code Online (Sandbox Code Playgroud)

两种语法都有效.除了编码风格之外,这些语法之间是否有任何技术差异?在任何方面,语法之一是否优于其他语法?

Alo*_*ave 45

第一个语法:
try块的范围在成员初始化列表完成后开始,因此在此初始化期间抛出的任何异常都不会被此try-catch块捕获.

第二种语法:
它确保如果在Member Initialization列表中抛出异常,那么您就能捕获异常.

第三个语法:
它确保从函数体内的try块的起始括号之间抛出的任何异常被适当地捕获,这将意味着在参数传递期间引起的任何异常(如果有的话可能发生)将不会在此尝试中被捕获 - 块块.

所以是的,他们在提供什么功能方面完全不同.


编辑:
在构造函数和析构函数中使用第二种语法(function-try-block)时要考虑的一些准则:

根据C++标准,

如果catch块没有抛出(重新抛出原始异常,或抛出新的东西),并且控制到达构造函数或析构函数的catch块的末尾,则会自动重新抛出原始异常.

简单来说:
构造函数或析构函数function-try-block的处理程序代码必须通过发出一些异常来完成.

准则1:
构造函数 - try-block处理程序只有一个目的 - 转换异常.(也许要做日志记录或其他一些副作用.)它们对任何其他目的都没用.

从析构函数中抛出异常是一个坏主意,看看这里知道原因.
准则2:
析构函数 - try-blocks根本没有实际用途.它们永远不应该有任何东西需要检测,即使由于恶意代码而有某些东西需要检测,处理程序也不会对它做任何事情非常有用,因为它无法抑制异常.

准则3:
始终在构造函数或析构函数体内的本地try-block处理程序中清理非托管资源获取,从不在构造函数或析构函数中使用try-try-block处理程序.


对于Standardese粉丝:

C++标准,第15.3条,第15段:

如果返回语句出现在构造函数的function-try-block的处理程序中,则程序格式错误.

C++标准,第15.3条,第16段:

如果控制到达构造函数或析构函数的function-try-block的处理程序的末尾,则重新抛出正在处理的异常.否则,当控制到达function-try-block(6.6.3)的处理程序的末尾时,函数返回.流出函数try-block的末尾相当于没有值的返回; 这导致值返回函数(6.6.3)中的未定义行为.


参考文献:
看一看这个必须阅读资源此处了解更多详情和解释.

  • @MatthieuM.§15.3/ 15*如果**返回**语句出现在**构造函数**的function-try-block的处理程序中,则该程序**形成错误**.*§15.3/16*如果控制到达构造函数或析构函数**的function-try-block的处理程序的末尾,则处理的异常是**rethrown.否则,当控制到达function-try-block(6.6.3)的处理程序的末尾时,函数返回.流出函数try-block的末尾相当于没有值的返回; 这导致值返回函数(6.6.3)中的未定义行为.* (2认同)

Gen*_*yev 9

Function-try-block主要在构造函数中很有用,因为在初始化列表中没有其他方法可以捕获异常.在析构函数中,必须小心返回catch块,因为异常将被自动重新抛出.(并且在良好的设计中,析构函数不能抛出.)在正常函数中,此功能无用.编辑:一篇旧的但仍然很好的文章:http://drdobbs.com/184401316