此代码在Visual Studio 2015更新3中编译(此处:在线Visual C++编译器,在我在线尝试过的其他编译器中没有(GCC和CLANG),给出重新声明错误
vectorv = {1,2,3}; for (auto i : v) { printf("%d ", i); int i = 99; printf("%d ", i); }
输出:1 99 2 99 3 99
VS C++在线编译器(版本:19.10.24903.0)警告:
警告C4456:'i'声明隐藏了之前的本地声明
C++ 11规范中是否有一些空间允许两种实现都有效?
在我看来,VS2015正在为"auto i"创建一个范围,并且是循环体的内部范围.
正如同事建议的那样,添加一个额外的范围,在我测试的其他编译器中编译得很好(不是我想要这个,只是为了好奇):
vectorv = {1,2,3}; for (auto i : v) {{ printf("%d ", i); int i = 99; printf("%d ", i); }}
谢谢
编辑: 好的,在阅读了另一个问题后,基于范围的for循环中的变量重新声明和"Angew"的答案,我相信VS实际上是正确的.
我在这里读到:cpp参考
鉴于此语法描述:
for ( range_declaration : range_expression ) loop_statement
这相当于:
{ auto && __range = range_expression ; for (auto __begin = begin_expr, __end = end_expr; __begin != __end; ++__begin) { range_declaration = *__begin; loop_statement } }
我知道loop_statement实际上是我的整个块,包括括号,因此重新定义确实在内部块中,因此是有效的.
编辑2: 我的上一次编辑,为了将来的参考,阅读传统的for循环语法是一个类似的情况(循环的cpp)作为基于范围:
for ( init-statement condition(optional); iteration_expression(optional) ) statement
"以上语法产生的代码相当于:"
{ init_statement while ( condition ) { statement iteration_expression ; } }
所以回过头来看,我也可以解释/解析语句作为我的内部块,包括大括号,我至少期望在其中编译器的一致行为.但是所有编译器都会因为传统的for循环重新声明错误而挽救.
N4606(C++ 17 draft)3.3.3 basic.scope.block,第4节说
在init-statement,for-range-declaration以及if,while,for和switch语句的条件中声明的名称是if,while,for或switch语句(包括受控语句)的本地名称,以及不得在该陈述的后续条件下,也不得在受控陈述的最外面的区块(或对于if语句,任何最外面的区块)重新宣布; 见6.4
缩短:
在... for-range-declaration ...中声明的名称是... for ...的本地名称,不得在该语句的后续条件中重新声明,也不得在最外层的块中重新声明
我读到这个说不应该被允许.