在基于范围的 for 循环中重新声明变量
Posted
技术标签:
【中文标题】在基于范围的 for 循环中重新声明变量【英文标题】:Redeclaration of variable in range-based for loops 【发布时间】:2014-07-02 08:15:01 【问题描述】:此代码在 GCC 4.8.1 中失败,但在 MSVC2013 中有效:
#include <vector>
#include <string>
int main()
std::vector<int> V1,2,3,4,5;
for (auto i : V)
std::string i = "oups";
GCC 4.8.1 告诉:
prog.cpp:10:17: error: redeclaration of ‘std::string i’
std::string i = "oups";
^
这是 MSVC 2013 编译器中的一些错误吗?
【问题讨论】:
【参考方案1】:是的,这是一个错误,但在 GCC 中。 C++11[stmt.ranged] 明确指出您的基于范围的for
循环等同于:
auto && __range = (V);
for ( auto __begin = __range.begin(),
__end = __range.end();
__begin != __end;
++__begin )
auto i = *__begin;
std::string i = "oups";
所以内部i
应该简单地隐藏循环控制i
没有任何问题。
而且,正如live example 所示,当这样拼写时,GCC 实际上接受它就好了。
【讨论】:
所以您的意思是基于范围的 for 和“正常 for”的行为不应该相同? @Korchkidu 是的,他们在这方面的表现确实不同。 是的,确实如此。似乎基于范围的 for 循环将 for-range-declaration 置于“中间”范围内。所以实际上,在外部范围内重新声明变量也是可以的。至少可以说这是违反直觉的。 [stmt.ranged] 中的 for rage 循环与您所写的不同。声明没有范围(在您的情况下为std::string i = "oups";
)
@BЈовић 它有什么不同?请注意,我已经根据 OP 的情况和要点将begin-expr
和end-expr
替换为它们的定义。我没有提供基于范围的 for
循环的一般定义,而是展示了 OP 的循环在形式上等同于什么。【参考方案2】:
这是 GCC 和 Clang 中的一个错误
见Range Based For-loop
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;
// Notice brace
loop_statement
// Notice ending brace
另一方面,在 Visual C++ 2013 上
for (auto i : V) std::string i = "oups";
/* match this with equivalent for-loop
loop-statement aren't in braces
*/
不应该编译。
【讨论】:
【参考方案3】:c++11 [stmt.ranged] 告诉 range-for 循环扩展为:
auto && __range = range-init;
for ( auto __begin = begin-expr,
__end = end-expr;
__begin != __end;
++__begin )
for-range-declaration = *__begin;
statement
与其他答案相反,我声称这些语句没有作用域,这是 MSVC 的错误(不是 gcc 或 clang)。
【讨论】:
基于范围的for循环的产生是“for
(
for-range-declaration:
表达式@987654325 @声明”。该生产中没有文字
,这意味着 OP 案例中的 statement 是整个复合语句。以上是关于在基于范围的 for 循环中重新声明变量的主要内容,如果未能解决你的问题,请参考以下文章