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

2021-12-29 00:00:00 syntax try-catch c++ function-try-block

我最近在 try-catch 函数中遇到了这种语法.

I came across this syntax recently for 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(...) {}
};

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

Both syntax are valid. Is there any technical difference between these syntax apart from coding style ? Is one of the syntax superior to other by any aspect ?

推荐答案

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

The First Syntax:
The scope of the try block starts after the Member Initialization list has been completed, So any exception thrown during Member Initialization will not be caught by this try-catch block.

第二种语法:
它确保如果在成员初始化列表期间抛出异常,则您能够捕获该异常.

The second syntax:
It ensures that if an exception gets thrown during Member Initialization list then you are able to catch the exception.

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

The Third Syntax:
It ensures that any exception thrown from betwen the starting brace of the try block inside the function body gets caught appropriately, It would mean any exception caused during the argument passing(if any can occur) will not be caught in this try-catch block.

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

So yes they are disinctly different in what functionality they provide.


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


Some guidelines to be considered while using the second syntax(function-try-block) in constructors & destructors:

根据 C++ 标准,

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

If the catch block does not throw (either rethrow the original exception, or throw something new), and control reaches the end of the catch block of a constructor or destructor, then the original exception is automatically rethrown.

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

In Simple words:
A constructor or destructor function-try-block's handler code MUST finish by emitting some exception.

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

从析构函数中抛出异常是个坏主意,看看此处 了解原因.准则 2:
析构函数尝试块根本没有实际用途.永远不应该有任何东西可供他们检测,即使由于恶意代码而检测到某些东西,处理程序也没有太大用处,因为它无法抑制异常.

Throwing a exception from destructors is an bad idea, Take a look here to know why.
Guideline 2:
Destructor function-try-blocks have no practical use at all. There should never be anything for them to detect, and even if there were something to detect because of evil code, the handler is not very useful for doing anything about it because it can not suppress the exception.

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

Guideline 3:
Always clean up unmanaged resource acquisition in local try-block handlers within the constructor or destructor body, never in constructor or destructor function-try-block handlers.

对于标准粉丝:

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

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

If a return statement appears in a handler of the function-try-block of a constructor, the program is ill-formed.

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

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

The exception being handled is rethrown if control reaches the end of a handler of the function-try-block of a constructor or destructor. Otherwise, a function returns when control reaches the end of a handler for the function-try-block (6.6.3). Flowing off the end of a function-try-block is equivalent to a return with no value; this results in undefined behavior in a value-returning function (6.6.3).

<小时>

参考资料:
看看这个必读资源这里 了解更多详情 &说明.


References:
Have a look at this must read resource here for more details & explanation.

相关文章