在基于范围的for的表达式和声明中具有相同名称的标识符

Identifier with the same name in both expression and declaration of range-based for

本文关键字:标识符 声明 表达式 于范围 范围 for      更新时间:2023-10-16

在基于范围的for循环中声明与我在循环的表达式语句中使用的名称相同的循环变量是否合法?我希望这个例子能让你明白。

#include <iostream>
#include <vector>
struct bar {
    std::vector<int> nums;
};
int main()
{
    bar b;
    b.nums = {1, 2, 3};
    for(int b : b.nums)
        std::cout << b << std::endl;   
}

从我阅读的c++ 2011 6.5.4,你的代码:

bar b;
for(int b : b.nums)
    std::cout << b << std::endl;

应转换为:

bar b;
{
   auto && __range = b.nums;
   for (auto __begin = __range.begin(), __end = __range.end(); __begin != __end; ++__begin ) {
       int b = *__begin;
       std::cout << b << std::endl;
   }
}

这对我来说意味着clang是正确的

叮当声是正确的

c++ 11标准第6.5.4/1段定义了基于范围的for语句如下:

对于形式为

的基于范围的 For语句
for ( for-range-declaration : expression ) statement

range-init等价于用圆括号括起来的表达式

( expression )

和基于范围的 for语句,格式为

for ( for-range-declaration : braced-init-list ) statement

range-init等价于带括号的init-list。在每种情况下,基于范围的for语句都是等效的

{
    auto && __range = range-init;
    for ( auto __begin = begin-expr,
          __end = end-expr;
          __begin != __end;
          ++__begin ) {
        for-range-declaration = *__begin;
        statement
    }
}

从上面可以看到,变量b,对应于for-range-declaration,是在嵌套块语句中声明的,而初始化器range-init(对应于b.nums)出现在父作用域中,其中b应该解析为类型为bar的对象。

无论如何,这个错误现在已经在gcc主干上修复了。:)