C++ 跳转的吊舱和规则

C++ 跳转的吊舱和规则,c++,C++,从本常见问题解答: 我们有这部分: 后藤声明。您可能知道,通过goto从某个变量尚未在作用域中的点跳转到该变量已在作用域中的点是非法的(编译器应发出错误)。仅当变量为非POD类型时,此限制才适用。在下面的示例中,f()格式不正确,而g()格式正确。请注意,Microsoft编译器对这一规则过于宽松,在这两种情况下都会发出警告 int f() { struct NonPOD { NonPOD(){}}; goto label; NonPOD x; label: return 0;

从本常见问题解答:

我们有这部分:

后藤声明。您可能知道,通过goto从某个变量尚未在作用域中的点跳转到该变量已在作用域中的点是非法的(编译器应发出错误)。仅当变量为非POD类型时,此限制才适用。在下面的示例中,f()格式不正确,而g()格式正确。请注意,Microsoft编译器对这一规则过于宽松,在这两种情况下都会发出警告

int f() {
  struct NonPOD { NonPOD(){}};
  goto label;
  NonPOD x;
label:
  return 0;
}

int g(){
  struct POD {int i;  char c;};
  goto label;
  POD x;
label:
  return 0;
}
我想知道为什么会有不同?看起来可能是这样,即使吊舱是 在goto之后声明,它已经初始化,无需执行更多操作,而 非POD未初始化。还是我找错了树了?

Goto不能跳过初始化,除非它出现在一个块中,并且你跳过了整个块


对于非POD,称为ctor。这是必要的,并且必须发生在变量出现的地方。如果您可以跳过它,则可以使用断开状态访问该变量。在
f
的情况下,
x
的析构函数(由编译器根据构造函数自动提供,从而使
结构成为非POD类型)将被称为“返回时”。对尚未构造的对象调用析构函数不是一个好计划。如果我们让这段代码变得足够复杂,我们很容易就会陷入这样一种场景:编译器很难知道哪些对象已经初始化,哪些还没有初始化,因此更安全的做法是只禁止跳过任何初始化(这种情况的另一种常见情况是使用
开关
-语句时,在每种情况下都会引入一些对象:

switch(x)
{
   case 1:
      NonPod x;
      ..
      break;
   case 2: 
      ...
}

是一个类似的构造(同样糟糕)。

这意味着在POD的情况下初始化已经完成,但在非POD的情况下它还没有完成。POD不能有一个ctor-这是一个要求。但是我认为如果使用{}init,这也会失败。好吧,构造函数是隐式的,它必须在某个点上运行。goto不能跳过初始化,所以POD必须已经初始化。我正在试图弄清楚这是什么时候发生的。在您的示例中,POD只是“普通的旧数据”,这意味着它没有构造函数、Destructor或虚拟方法(或在结构中包含以下内容之一的内容,例如,
std::string
将使其成为非POD)。
g()中的
x
未初始化-根据堆栈中的内容,它有一些随机垃圾,但没有初始化。因此,你是说POD未初始化。如果是,则goto应该无法跳过它。因此POD已经初始化,goto可以跳过它。POD是何时初始化的?