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

inf*_*inf 16 c++ scope for-loop c++11

在基于范围的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;   
}
Run Code Online (Sandbox Code Playgroud)

当clang 3.2允许时,gcc 4.8给出错误.

Bil*_*nch 11

从我阅读C++ 2011 6.5.4开始,您的代码为:

bar b;

for(int b : b.nums)
    std::cout << b << std::endl;
Run Code Online (Sandbox Code Playgroud)

应转换为:

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;
   }
}
Run Code Online (Sandbox Code Playgroud)

这对我来说意味着铿锵是正确的.


And*_*owl 9

Clang是对的.

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

对于基于范围的表单声明

for ( for-range-declaration : expression ) statement
Run Code Online (Sandbox Code Playgroud)

让range-init等同于括号括起来的表达式

( expression )
Run Code Online (Sandbox Code Playgroud)

以及基于范围的表格声明

for ( for-range-declaration : braced-init-list ) statement
Run Code Online (Sandbox Code Playgroud)

让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
    }
}
Run Code Online (Sandbox Code Playgroud)

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

  • 从标准的字面解释来看,这并不容易......在'auto && __range = range-init;``range-init`实际上是`b.num`,但`int b`没有进入在定义中直到5行......但是再次看到原始代码,可以预期`int b`隐藏`bar b`. (3认同)