我在尝试解决一个复杂的“嵌套条件”问题时,想到了以下代码:
goto error;
if (false)
{
error:
cout << "error block" << endl;
}
else
{
cout << "else block" << endl;
}
当我运行这段代码时,只有错误块
被显示出来,正如预期的那样(我猜?)。但是这是否是所有编译器都定义好的行为?我在尝试解决一个复杂的“嵌套条件”问题时,想到了以下代码:
goto error;
if (false)
{
error:
cout << "error block" << endl;
}
else
{
cout << "else block" << endl;
}
当我运行这段代码时,只有错误块
被显示出来,正如预期的那样(我猜?)。但是这是否是所有编译器都定义好的行为?是的,这是被很好地定义了。请参阅stmt.goto#1
goto语句无条件地将控制转移到由标识符标记的语句。该标识符应为当前函数中的标签。
有一些限制,例如,case标签不能跨越非平凡初始化。
goto error;
int i = 42;
error: // error: crosses initialization of i
但这些不适用于你的例子。此外,在初始化交叉的情况下,这是一个严格的编译器错误,因此您无需担心未定义的行为。
请注意,一旦跳转到error
标签,您实际上位于if
条件的真分支中,而且不管您是通过goto
到达的,都无关紧要。因此,保证不会执行else
分支。
if
条件,可能会导致跳转到if
后跳过else
块。 - Barmarint
初始化另一个 int
不是很简单吗?std::is_trivially_constructible<int, int>::value
是 true
。 - NotNik.我的看法:
如果你的编译器有优化器,代码会按以下方式减少:
// more code here
goto error; // this go directly to the label
if (false)
{
error:
cout << "error block" << endl;
// this skips else clause
}
else
{
cout << "else block" << endl;
}
// more code here
所以编译后的代码只是这样的:
// more code here
{
cout << "error block" << endl;
}
// more code here
这里是Godbolt的链接:
https://gcc.godbolt.org/z/nY6E166Pz
我稍微简化了代码,这样汇编就更易读了。
goto
到该标签的事实意味着它实际上是可达的。 - François Andrieuxgoto
声名狼藉,但在某些情况下它是一个不错的选择(或者至少是较小的恶)。Objective-C(以及间接地,Objective-C++)在Cocoa代码中经常使用goto
进行错误检测和跳转到资源清理 - 尽管这些是堂兄弟语言而不是C++本身。更严格的C++场景是一些状态机可以用goto
优雅地表达,或者用更扭曲/复杂的方式避免goto
(可能效率更低...但我不应该低估聪明的优化器)。 - Eljay