【问题标题】:Why Is This Loop Variable Accessible Outside Loop Scope?为什么这个循环变量可以在循环范围之外访问?
【发布时间】:2018-09-21 01:12:16
【问题描述】:

在浏览一些 C++ 代码时,我遇到了以下几行:

for (int i = 0; i < count; i++) {
        if (&array[i].GetData() == el)
            break;
}
if (i < count) {
   // .. Do something
}

我很惊讶地看到循环计数器变量i 可以在循环外访问!

为了确保循环外的i与循环内的相同,我将循环变量名改为i1。

for (int i1 = 0; i1 < count; i1++) {
        if (&array[i1].GetData() == el)
            break;
}
if (i < count) {    // COMPILATION ERROR: Identifier i is undefined
   // .. Do something
}

这导致if(i &lt; count) 行出现编译错误:

标识符“i”未定义。

发生了什么事?这太基本了,不能成为编译器错误。如果父作用域中有另一个i,则不会出现编译错误。我错过了什么吗?我正在使用 Visual Studio 2015。

【问题讨论】:

  • 你使用什么编译标志? (例如:您是否打开了/permissive 和/或/Za?)
  • 看起来像是这里描述的东西的痕迹stackoverflow.com/questions/49447957/…
  • 这是微软编译器的“扩展”。由于历史原因,它默认启用。
  • 您是否设置了/Zc:forScope-(IDE 的 C++ 属性中的“强制 For 循环范围内的一致性”)选项?这会导致 MC++ 2015 编译器使用扩展 for 循环变量范围的遗留行为。
  • 这绝对不是标准行为,你绝对不应该指望它。您当前标志的编译器可能会接受这一点,但另一个编译器,甚至只是具有相同编译器的不同版本或标志,可能不会(老实说,imo 不应该)

标签: c++ visual-studio


【解决方案1】:

Visual Studio 过去具有延长在 for(...) 构造中声明的变量的生命周期和可访问性的功能(在 C++98 标准出现之前的普通 C 行为的保留)。在旧项目中默认启用此行为。

Microsoft 意识到这种(对于 C++ 的)不符合标准的行为可能是不可取的,并提供了 /Zc:forScope 编译器选项来控制这种行为(最近默认启用此开关,恢复标准 C++ 一致性)。

检查/Zc:forScope 是否在C++ -> Language 附加项下的项目设置中设置。如果没有,请设置它。

注意:您还可以选择在此处设置 /Zc:forScope- 以显式启用非标准行为,以防您有依赖它的旧代码。

【讨论】:

  • 不仅是 VS,还有 gcc。这是在有标准之前。见stackoverflow.com/questions/49447957/…
  • 啊,我不知道;它只是那些可以给你最讨厌的惊喜的事情之一(很久以前有一个非常“有趣”的错误,变量名中有错字 - 不幸的是,错字与在 for(... ) 较早。试图找到那个非常“有趣”。)
  • 我尝试编辑此内容,以消除 MS 犯了错误,即修复缓慢的暗示。但我厌倦了它。曾经有一段时间(在 C++98 之前?)旧的 C 风格行为是唯一的行为。最初的 Cfront(我使用的)就是这样做的。当标准发生变化时,微软和其他公司很快就采用了它,但将旧行为作为默认行为,以免破坏现有项目。这是正确的做法。
  • @Jive Dadson 我已经更新了我的答案以引用它。我只是希望他们也不会在默认情况下为 C++ 项目启用它(至少我记得使用 VS2003——又是很久以前——创建一个 C++ 项目并被它弄糊涂了)
  • 我正在查看一些 17 年前的代码,由于这种行为而无法编译。我不明白为什么它在过去编译。我很惊讶原作者忽略了 C++ 的范围标准。
猜你喜欢
  • 2012-11-18
  • 2016-02-12
  • 1970-01-01
  • 2011-11-12
  • 1970-01-01
  • 1970-01-01
  • 2023-03-04
  • 1970-01-01
相关资源
最近更新 更多