基于现有变量循环的范围

时间:2016-07-27 13:39:05

标签: c++ c++11 for-loop gcc visual-c++

在C ++ 11中使用基于for循环的范围和现有变量,我希望该变量用循环后的最后一次迭代的值填充。但是,当我测试它时,我得到了不同的结果。

示例:

#include <iostream>
#include <vector>
using namespace std;

int main() {
  std::vector<int> v;
  v.push_back(2);
  v.push_back(43);
  v.push_back(99);

  int last = -50;
  for (last : v)
    std::cout << ":" << last << "\n";

  std::cout << last;
  return 0;
}
  1. MSVC 2013似乎不支持基于范围的没有类型声明的循环
  2. GCC-5.1自动引入新变量或将其设置回初始值,给出

      

    :2个
      :43
      99
      -50

  3. 我猜MSVC再次成为MSVC,但是GCC在这里呢?为什么最后一行last不是99

    鉴于definition by the standard,我希望我在第一句话中描述的行为。

    {
      auto && __range = range_expression ; 
      for (auto __begin = begin_expr, __end = end_expr; 
           __begin != __end; ++__begin) { 
        range_declaration = *__begin; 
        loop_statement 
      } 
    } 
    

    range_declarationlast而不是int last,这应修改现有变量。

4 个答案:

答案 0 :(得分:18)

GCC实施了标准提案n3994,这表明for (elem : range)for (auto&& elem : range)的语法糖。这并没有进入C ++ 17,因此已从更新版本的GCC中删除了该功能。

用于迭代范围的命名变量必须是[stmt.ranged]的声明,因此您的代码不应该编译。

答案 1 :(得分:9)

您的代码无法从gcc 6.1(以及所有clang版本)开始编译:

main.cpp:12:8: error: range-based for loop requires type for loop variable
  for (last : v)
       ^
       auto &&

看起来以前的版本在这里隐式使用了auto。你得到-50作为最后一个输出的事实是因为for引入了last的本地范围,所以在for结束之后,使用了最后一个外部范围。

我做了一点挖掘,这是故意在gcc:N3994, terse range-for下进行的,很快就会做到:

A range-based for statement of the form
    for ( for-range-identifier : for-range-initializer ) statement
is equivalent to
    for ( auto&& for-range-identifier : for-range-initializer ) statement

然后它没有进入c ++ 17并在此删除:

https://gcc.gnu.org/viewcvs/gcc?view=revision&revision=229632

答案 2 :(得分:0)

根据标准,基于for循环的范围产生与:

相同的输出
{
  auto&& __range = expression;
  for (auto __begin = begin-expression,
            __end = end-expression;
       __begin != __end;
       ++__begin)
  {
    declaration = *__begin;
    statement
  }
}

如您所见,迭代变量__begin正在其自己的范围内定义。

为什么最后一行中的最后一个不是99?

您有两个名为last的变量。一个属于main函数的范围,并保存值-50。第二个变量在基于循环的范围内定义。

在循环内部,打印last变量打印来自同一范围的变量(即来自基于循环的范围)。然而,在循环之后,打印last将再次打印来自同一范围的变量,该范围是-50

答案 3 :(得分:0)

你的程序没有用我的g ++ 4.9.2编译。

使用clang ++ 3.5进行编译(带有警告:&#34;基于范围的for循环,带隐式推导类型是C ++ 1z扩展[-Wc ++ 1z-extensions]&#34;)

但clang ++使用不同的last变量

使用以下修改过的程序

#include <iostream>
#include <vector>
using namespace std;

int main() {
  std::vector<int> v;
  v.push_back(2);
  v.push_back(43);
  v.push_back(99);

  int last = -50;

  std::cout << "extern last pointer: " << long(&last) << '\n';

  for ( last : v)
   {
     std::cout << ": " << last << " ; pointer: " << long(&last) << '\n';
   }

  std::cout << "extern last pointer again: " << long(&last) << '\n';
  std::cout << ": " << last << std::endl;

  return 0;
}

我得到以下输出

extern last pointer: 140721376927168
: 2 ; pointer: 38101008
: 43 ; pointer: 38101012
: 99 ; pointer: 38101016
extern last pointer again: 140721376927168
: -50