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;   
}

gcc 4.8 给出一个错误,而 clang 3.2 允许它。

4

3 回答 3

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

于 2013-05-06T21:15:16.023 回答
9

铿锵是对的

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等价于花括号初始化列表。在每种情况下,基于范围的 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

于 2013-05-06T21:04:35.513 回答
2

对于它的价值,这个错误现在已经在 gcc 主干上修复了。:)

于 2015-10-01T19:25:35.157 回答