考虑以下代码:
void foo()
{
{
CSomeClass bar;
// Some code here...
goto label;
// and here...
}
label:
// and here...
}
会调用 bar 的析构函数吗?
考虑以下代码:
void foo()
{
{
CSomeClass bar;
// Some code here...
goto label;
// and here...
}
label:
// and here...
}
会调用 bar 的析构函数吗?
C++ 标准说:
在从范围退出时(无论如何完成),对于在该范围中声明的所有具有自动存储持续时间 (3.7.2) 的构造对象(命名对象或临时对象)调用析构函数 (12.4),其顺序与声明的相反。
所以答案是“是”。
是的,他们会被召唤。
更新:( 这样做没关系,goto 并不比抛出虚拟异常或使用 bools/ifs 摆脱事物更糟糕。函数内部的简单 goto 不会使其成为意大利面条代码。)
1) 是的。2)不要这样做。
详细说明:从概念上讲,这与通过 a 离开循环没有什么不同break
。 goto
但是,强烈、强烈地劝阻。几乎从不需要使用goto
,并且应该仔细检查任何使用以找出发生了什么。
是的,正如其他人所说。C++ 指定/强制执行此操作。
但只是为了完整性:如果您goto
使用在某些编译器中找到的计算goto
扩展 - gcc,clang,可能还有其他但不包括我最后知道的 MSVC - 是否会调用对象的析构函数是非常模糊的. 当 agoto
转到单个位置时,非常清楚必须在控制流传输之前调用哪些析构函数。但是对于 computed goto
,可能需要动态调用不同的析构函数,以提供“预期的”语义。在这些情况下,我不确定实现此扩展的编译器会做什么。我遇到这种情况的记忆是,当计算-goto
可能会留下一个带有非平凡析构函数的对象的作用域,声称不会调用析构函数。在某些情况下可能很好,在其他情况下则不然。我不知道其他编译器做了什么。如果您想将 computedgoto
与具有非平凡析构函数的对象一起使用,请注意这个问题。
尽管要调用析构函数,但请注意 gcc 有一个错误:
如果您的代码具有以下形式,您在其中返回类并执行应该导致其被破坏的跳转,则将跳过析构函数。
CSomeClass foo()
{
label:
CSomeClass bar;
// Some code here...
if (someCondition)
goto label; // if this jump is taken, bar is not destructed in gcc
return bar;
}