函数的try-catch语法的区别

Difference between try-catch syntax for function

本文关键字:区别 语法 try-catch 函数      更新时间:2023-10-16

我最近在try-catch for 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(...) {}
};

两种语法都是有效的。除了编码风格之外,这些语法在技术上有什么不同吗?

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

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

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

所以它们在提供的功能上有明显的不同。


编辑:


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

根据c++标准,

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

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

指南1:
构造函数-try-block处理程序只有一个目的——转换异常。(也可能是为了做日志记录或其他一些副作用。)它们没有任何其他用途

从析构函数抛出异常是一个坏主意,看一下这里的了解原因。
指南2:
析构函数-try-block根本没有实际用途。它们不应该检测到任何东西,即使由于恶意代码而检测到某些东西,处理程序对于做任何事情也不是很有用,因为它不能抑制异常。

准则3:
总是在构造函数或析构函数体中的局部尝试块处理程序中清除非托管资源获取,而不是在构造函数或析构函数的尝试块处理程序中。


标准风扇:

c++标准条款15.3款15:

如果return语句出现在构造函数的function-try块的处理程序中,则该程序是病态的。

c++标准条款15.3款16:

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


引用:
看看这个必须阅读资源在这里了解更多细节& &;解释。

Function-try-block主要用于构造函数,因为在初始化列表中没有其他方法捕获异常。在析构函数中,必须小心返回catch块,因为异常将被自动重新抛出。(在良好的设计中,析构函数一定不能抛出。)在普通函数中,这个特性是没有用的。编辑:一篇老文章:http://drdobbs.com/184401316

不妨引用规范…或者至少是草稿。

第15(4)节:

一个函数-try-block处理程序-seq元素初始化器(如果存在)和复合语句相关联。在复合语句执行期间抛出的异常,或者对于构造函数和析构函数,分别在类的子对象的初始化或销毁期间抛出的异常,将控制转移到函数-try-block中的处理程序中,就像在try-block执行期间抛出的异常将控制转移到其他处理程序中一样。

(这里的处理程序-seqcatch之后的东西,compound-statement是函数体)

因此,构造函数或析构函数上的"function try块"捕获由元素初始化器和子对象的构造或析构引起的异常。

对于构造函数或析构函数以外的函数,它与简单地包装函数体相同。(嗯,就我看说明书所知)

有趣的功能,对我来说是新的。谢谢你提出来。

"something different"的例子将初始化列表的处理置于try块的作用域中。