【问题标题】:Redeclaration of variable in range-based for loops在基于范围的 for 循环中重新声明变量
【发布时间】:2014-07-02 08:15:01
【问题描述】:

此代码在 GCC 4.8.1 中失败,但在 MSVC2013 中有效:

#include <vector>
#include <string>

int main()
{
  std::vector<int> V{1,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 编译器中的一些错误吗?

【问题讨论】:

    标签: c++ visual-studio gcc c++11


    【解决方案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 是整个复合语句。
      猜你喜欢
      • 1970-01-01
      • 2016-10-22
      • 2015-11-29
      • 1970-01-01
      • 1970-01-01
      • 2011-02-13
      • 1970-01-01
      • 2018-10-11
      • 2018-05-13
      相关资源
      最近更新 更多