function的try-catch语法之间的区别

我最近遇到了这个语法的try-catch函数。

 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(...) {} }; 

两种语法都是有效的 。 除了编码风格之外,这些语法还有什么技术上的区别吗? 从任何方面来看,其中一种语法是否优于其他语法?

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

第二个语法:
它确保如果在成员初始化列表中抛出一个exception,那么你可以捕获exception。

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

所以是的,他们提供什么样的function是完全不同的。


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

按照C ++标准,

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

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

准则1:
构造函数的function尝试块处理程序只有一个目的 – 翻译exception。 (也许做logging或其他副作用。)他们没有任何其他用途。

从析构函数中抛出一个exception是一个糟糕的主意,请看看这里来了解原因。
准则2:
析构函数try-blocks根本没有实际用处。 不应该有任何东西让他们去检测,即使有些东西因为邪恶的代码而被检测到,处理程序对于处理任何事情都不是很有用,因为它不能抑制exception。

准则3:
总是清理构造函数或析构函数体内的本地try-block处理程序中的非托pipe资源获取,而不是在构造函数或析构函数try-block处理程序中清理。


对于Standarde粉丝:

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

如果return语句出现在构造函数的function-try-block的处理程序中,则该程序是格式不正确的。

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

如果控制到达构造函数或析构函数的function-try-block处理程序的末尾,则会重新处理正在处理的exception。 否则,当控制到达函数尝试块(6.6.3)的句柄结束时,函数返回。 在函数try块的结尾stream动相当于没有值的返回; 这会在返回值函数(6.6.3)中导致未定义的行为。


参考文献:
看看这里必须阅读资源了解更多细节和解释。

Function-try-block主要在构造函数中使用,因为在初始化列表中没有捕获exception的其他方法。 在析构函数中,必须小心地返回catch块,因为exception会自动重新抛出。 (在良好的devise析构函数不能抛出。)在正常的function这个function是没有用的。 编辑:一个旧的,但仍然很好的文章: http : //drdobbs.com/184401316

也可能引用规范…或至less是一个草案 。

第15(4)条:

一个function-try-block将一个handler-seqctor-initializer (如果存在)和compound-statement关联起来。 复合语句执行期间抛出exception,或者对于构造函数和析构函数,分别在类的子对象的初始化或销毁期间,将控制权转交给函数尝试块中的处理程序,方法与抛出的exception相同在对其他处理程序执行try-block转移控制期间。

(这里handler-seqcatch之后的东西,而compound-statement是函数体。)

所以构造函数或析构函数的“函数try块”捕获ctor初始化函数抛出的exception,以及构造或破坏子对象。

在构造函数或析构函数以外的函数中,与简单地包装函数体相同。 (呃,就我所能看到的规格来看)。

有趣的function,对我来说是新的。 感谢您提出。

“不同的东西”例子把初始化器列表的处理放在try块的范围内。

Interesting Posts