在基于范围的 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-exprend-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 循环中重新声明变量的主要内容,如果未能解决你的问题,请参考以下文章

[C++11]基于范围的for循环

为啥在嵌套函数之外声明一个计数器变量会使循环慢 5 倍?

for循环变量声明为 final

在for循环声明中初始化变量的范围实际上不仅仅是块范围吗?

无法重新声明块范围变量(打字稿)

Vue(核心思想)