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

时间:2013-05-06 21:02:08

标签: c++ for-loop c++11 scope

在基于范围的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;   
}

gcc 4.8在clang 3.2允许时发出错误。

3 个答案:

答案 0 :(得分:11)

从我对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 是正确的。

答案 1 :(得分:9)

Clang是对的

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

  

对于表单

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

range-init 等同于括号

所包围的表达式
( expression )
     

以及基于范围的表单

的声明
for ( for-range-declaration : braced-init-list ) statement
     

range-init 等同于braced-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(对应于{{ 1}})出现在父作用域中,其中b.nums应解析为b类型的对象。

答案 2 :(得分:2)

为了它的价值,这个bug现在已经在gcc trunk上修复了。 :)