C++ 中“for”循环的范围规则与 C 中不同?

eas*_*000 20 c c++ scope for-loop

我注意到 C 和 C++ 的循环范围规则for不同。
例如,下面的代码在 C 编译器中合法,但在 C++ 编译器中不合法。

for (int i = 0; i < 10; ++i) {
    int i = 5;
}
Run Code Online (Sandbox Code Playgroud)

上面的代码在 C 中有效,但在 C++ 中给出了重新定义错误。
我的猜测是,C 编译器将循环视为循环内有另一个作用域,如下所示。

for (int i = 0; i < 10; ++i) {
    {
        int i = 5;
    }
}
Run Code Online (Sandbox Code Playgroud)

为什么 C 编译器允许在循环范围内定义第二个同名变量?这样做有什么特别的原因或优势吗?

Dan*_*ein 17

就标准而言,for循环作用域在 C 和 C++ 中的定义确实不同。在 C 语言中它们的定义如下:

6.8.5.3 for 语句

该声明

for ( 子句 1 ; 表达式 2 ; 表达式 3 ) 语句

行为如下:...

没有具体提及statement. 循环的顶层描述(标准中的“迭代语句”)指定:

迭代语句是一个块,其范围是其封闭块范围的严格子集。循环体也是一个块,其范围是迭代语句范围的严格子集。

正如您在问题中暗示的那样,代码如下:

for (int i = 0; i < 10; ++i)
    int i = 5;
Run Code Online (Sandbox Code Playgroud)

未声明新块的地方(请注意{ }重新声明周围缺少的内容) - 不是有效代码。


而在 C++ 中,有一个关于循环变量重新声明的具体参考:

8.6 迭代语句指定循环...如果在 init 语句或 for-range 声明中引入的名称在子语句的最外层块中重新声明,则程序格式错误


由于它与基本原理相关 - 可能 C++ 只是添加了限制作为对语言语义的改进,实际上以这种方式重新声明变量通常是一个错误。

可以说,此限制在 C 中也适用 - 但将此限制添加到 C 标准中会破坏与现有代码的向后兼容性,并且不太可能发生。