6

我有一些代码是从一个非常聪明的人那里继承而来的,他们喜欢使用 goto 离开 try 块,完全绕过 catch 块。

它确实有效,我怀疑这是合法的(我认为 C++ 标准说,在退出范围时,一切都会被正确清理,我认为这适用于编译器在我的平台上实现异常所必须做的任何事情) .

这真的合法吗?这不是我写过的东西(它太聪明了一半),但它显然有效,我只是想了解为什么这样可以。

4

4 回答 4

11

它可以是合法的,这取决于代码的作用。例如,我编写了从 catch 块中跳出的代码,它用于一种语言的运行时库(为简单起见,使用运行时库的代码没有实现安腾异常处理,而是使用 longjmp/setjmp 实现)。然而,运行时库通过 C++ 异常确实使用了它。并且需要一种机制来在它们之间干净地转移控制。

try {
  doSomethingThatMayFail();
} catch(DiagnosticException&) {
  goto unwind;
}

if(0) {
unwind:
  longjmp(&lastSafePoint, 0);
}

我把它放在一个宏里,这样写起来很方便。这里goto有必要清理诊断异常的异常处理期间分配的资源。

与往常一样,不要说“永远不要使用此功能”。相反,每次使用都必须仔细考虑。

于 2012-07-12T19:12:16.380 回答
10

标准说是的,它是合法且定义明确的:

C++2003:6.6 跳转语句

在从范围退出时(无论如何完成),对于在该范围中声明的所有具有自动存储持续时间 (3.7.2) 的构造对象(命名对象或临时对象),按照其声明的相反顺序调用析构函数 (12.4)。转移出循环、转移出块或返回具有自动存储持续时间的初始化变量涉及销毁具有自动存储持续时间的变量,这些变量在转移点的范围内但不在转移点的范围内。(参见 6.7 中的转移到块)。[注意:但是,可以终止程序(例如,通过调用 exit() 或 abort()(18.3))而不会破坏具有自动存储持续时间的类对象。]

我选择不首先评论使用的宗教含义goto

于 2012-07-12T19:08:21.703 回答
7

甚至比 C++03 标准关于跳转语句的部分更具体,它在“异常处理”子句 (15/2) 中对 try-blocks 进行了说明:

goto、break、return 或 continue 语句可用于将控制权转移到 try 块或处理程序之外。发生这种情况时,在 try 块中声明的每个变量都将在直接包含其声明的上下文中被销毁。

C++11 包含相同的措辞。

但是请注意,使用(or )跳转到 try 块是不行的:gotoswitch

不应使用 goto 或 switch 语句将控制转移到 try 块或处理程序中。

于 2012-07-12T19:12:35.490 回答
2

这是合法的。这是糟糕的代码。不要这样做。不要使用goto.

于 2012-07-12T19:07:13.653 回答