为什么不能在 switch 语句中声明变量?

新手上路,请多包涵

我一直想知道 - 为什么不能在 switch 语句中的 case 标签之后声明变量?在 C++ 中,您几乎可以在任何地方声明变量(并且在接近第一次使用时声明它们显然是一件好事),但以下仍然行不通:

 switch (val)
{
case VAL:
  // This won't work
  int newVal = 42;
  break;
case ANOTHER_VAL:
  ...
  break;
}

以上给了我以下错误(MSC):

“case”标签跳过“newVal”的初始化

这似乎也是其他语言的限制。为什么会出现这样的问题?

原文由 Rob 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.1k
2 个回答

Case 语句只是 标签。这意味着编译器会将其解释为直接跳转到标签。在 C++ 中,这里的问题是范围之一。您的大括号将范围定义为 switch 语句中的所有内容。这意味着您将留下一个范围,在该范围内将进一步执行跳转到跳过初始化的代码。

处理此问题的正确方法是定义特定于 case 语句的范围并在其中定义您的变量:

 switch (val)
{
case VAL:
{
  // This will work
  int newVal = 42;
  break;
}
case ANOTHER_VAL:
...
break;
}

原文由 TJ Seabrooks 发布,翻译遵循 CC BY-SA 4.0 许可协议

我最初为 这个问题 写了这个答案。但是,当我完成它时,我发现答案已关闭。所以我把它贴在这里,也许喜欢参考标准的人会觉得它很有帮助。

有问题的原始代码:

 int i;
i = 2;
switch(i)
{
    case 1:
        int k;
        break;
    case 2:
        k = 1;
        cout<<k<<endl;
        break;
}

其实有2个问题:

1、为什么我可以在 case 标签后面声明一个变量?

这是因为在 C++ 中,标签必须采用以下形式:

N3337 6.11

标记语句:

  • 属性说明符-seqopt case constant-expression : statement

并且在 C++ 声明语句 也被视为 _语句_(相对于 C ):

N3337 6/1:

_声明_:

声明-声明

2. 为什么我可以跳过变量声明然后使用它?

因为:N3337 6.73

可以转移到一个块中, 但不能以一种绕过初始化声明的方式。跳转的程序( switch 语句的条件到 case 标签的转移在这方面被认为是跳转。)

从具有自动存储持续时间的变量不在范围内的点到它在范围内的点是 格式错误的, 除非该变量具有标量类型、具有普通默认构造函数和普通析构函数的类类型、cv 限定版本这些类型之一,或上述类型之一的数组,并且在没有初始化程序的情况下声明(8.5)。

由于 k 是 _标量类型_,并且在声明点未初始化,因此可以跳过它的声明。这在语义上是等价的:

 goto label;

int x;

label:
cout << x << endl;

但是,如果 x 在声明点被初始化,这是不可能的:

  goto label;

    int x = 58; //error, jumping over declaration with initialization

    label:
    cout << x << endl;

原文由 PcAF 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题