为什么在通过goto向后退出时会调用析构函数

Eri*_*c Z 28 c++

可能重复:是否
会使用goto泄漏变量?

在下面的示例中,当goto调用"向后"时,A调用析构函数.为什么会那样?对象a不会离开它的范围,是吗?标准是否说明了这种行为goto

void f()
{
start:
    A a;
    goto start;
}
Run Code Online (Sandbox Code Playgroud)

Mar*_*ork 24

6.6跳转语句[stmt.jump]

第2段:

在从范围退出(但是已完成)时,在该范围内构造的具有自动存储持续时间(3.7.3)的对象将按其构造的相反顺序销毁.[注:对于临时学生,见12.2.-end note]从一个循环中转出一个循环,或者从具有自动存储持续时间的初始化变量返回过去涉及销毁具有自动存储持续时间的对象,这些对象在转移点但不在转移点的范围内. .(转入块中见6.7).[注意:但是,程序可以终止(例如,通过调用std :: exit()或std :: abort()(18.5)),而不会破坏具有自动存储持续时间的类对象. - 结束说明]

我认为重要的是:

或者通过自动存储持续时间返回过去的初始化变量涉及销毁


seh*_*ehe 14

对象的生命周期a从其声明开始,并延伸到包含它的块的末尾.

这意味着,在跳转到声明之前,你跳转到堆栈框架本地不存在的情况,所以它必须被破坏

  1. point of declaration一个名字的完整的声明符(第8章)后和它的初始化之前(如果有的话),[...](第3.3.2节)立即

  2. 块(6.3)中声明的名称是该块的本地名称; 它有块范围.其潜在范围从其声明点(3.3.2)开始,到其块结束时结束.在块作用域中声明的变量是局部变量.(§3.3.3)


NPE*_*NPE 12

以下是该标准的相关引用.它甚至包含一个几乎与您相同的示例:

C++ 11 6.7声明声明[stmt.dcl]

2 每次执行声明语句时,都会初始化具有自动存储持续时间(3.7.3)的变量.块中声明的具有自动存储持续时间的变量在从块(6.6)退出时被销毁.

3可以转换为块,但不能以初始化方式绕过声明.从具有自动存储持续时间的变量不在范围内的点跳转到其在范围内的点的程序是不正确的,除非该变量具有标量类型,具有普通默认构造函数的类类型和普通的析构函数,这些类型之一的cv限定版本,或者前面类型之一的数组,并且在没有初始值设定项的情况下声明(8.5).[例如:

void f() {
// ...
goto lx; // ill-formed: jump into scope of a
// ...
ly:
X a = 1;
// ...
lx:
goto ly; // OK, jump implies destructor
// call for a followed by construction
// again immediately following label ly
}
Run Code Online (Sandbox Code Playgroud)

- 末端的例子]

如示例中所述,goto暗示破坏.声明语句(A a;在您的代码中)表示每次跳转后重构执行构造函数.