在基于范围的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允许时发出错误。
答案 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上修复了。 :)