53

考虑以下代码:

void foo()
{
    {
        CSomeClass bar;

        // Some code here...

        goto label;

        // and here...
    }

label:
    // and here...
}

会调用 bar 的析构函数吗?

4

5 回答 5

76

C++ 标准说:

在从范围退出时(无论如何完成),对于在该范围中声明的所有具有自动存储持续时间 (3.7.2) 的构造对象(命名对象或临时对象)调用析构函数 (12.4),其顺序与声明的相反。

所以答案是“是”。

于 2010-07-05T13:47:42.533 回答
35

是的,他们会被召唤。

更新:( 这样做没关系,goto 并不比抛出虚拟异常或使用 bools/ifs 摆脱事物更糟糕。函数内部的简单 goto 不会使其成为意大利面条代码。)

于 2010-07-05T13:45:24.120 回答
8

1) 是的。2)不要这样做。

详细说明:从概念上讲,这与通过 a 离开循环没有什么不同breakgoto但是,强烈、强烈地劝阻。几乎从不需要使用goto,并且应该仔细检查任何使用以找出发生了什么。

于 2010-07-05T13:44:48.037 回答
7

是的,正如其他人所说。C++ 指定/强制执行此操作。

但只是为了完整性:如果您goto使用在某些编译器中找到的计算goto扩展 - gcc,clang,可能还有其他但包括我最后知道的 MSVC - 是否会调用对象的析构函数是非常模糊的. 当 agoto转到单个位置时,非常清楚必须在控制流传输之前调用哪些析构函数。但是对于 computed goto,可能需要动态调用不同的析构函数,以提供“预期的”语义。在这些情况下,我不确定实现此扩展的编译器会做什么。我遇到这种情况的记忆是,当计算-goto可能会留下一个带有非平凡析构函数的对象的作用域,声称不会调用析构函数。在某些情况下可能很好,在其他情况下则不然。我不知道其他编译器做了什么。如果您想将 computedgoto与具有非平凡析构函数的对象一起使用,请注意这个问题。

于 2013-04-10T17:14:55.970 回答
2

尽管要调用析构函数,但请注意 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;
}
于 2022-01-20T22:54:05.893 回答