基于现有变量循环的范围

时间:2022-12-16 22:20:27

Using a range based for loop in C++11 with an existing variable, I would expect that variable to be filled with the value of the last iteration after the loop. However, I've gotten different results when I tested it.

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

Example:

#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 doesn't seem to support range based for loops without type declaration
  2. MSVC 2013似乎不支持基于范围的循环而没有类型声明

  3. GCC-5.1 either automatically introduces a new variable or sets it back to the initial value, giving

    GCC-5.1自动引入一个新变量或将其设置回初始值,给出

    :2
    :43
    :99
    -50

    :2:43:99 -50

I guess MSVC is just being MSVC again, but what about GCC here? Why is last not 99 in the last line?

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


Given the definition by the standard, I would expect the behaviour I described in the first sentence.

根据标准的定义,我会期待我在第一句中描述的行为。

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

range_declaration being last and not int last, this should modify the existing variable.

range_declaration是last,而不是last last,这应该修改现有变量。

4 个解决方案

#1


17  

GCC implemented standards proposal n3994, which suggests that for (elem : range) be syntactic sugar for for (auto&& elem : range). This didn't make it into C++17, so the functionality has been removed from more recent versions of GCC.

海湾合作委员会实施了标准提案n3994,其中(elem:range)表示为(auto && elem:range)的语法糖。这没有进入C ++ 17,因此已从更新版本的GCC中删除了该功能。

The named variable used to iterate over the range must be a declaration according to [stmt.ranged], so your code shouldn't compile.

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

#2


9  

Your code does not compile starting with gcc 6.1 (and for all clang versions):

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

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

it looks like previous versions used auto implicitly here. The fact that you get -50 as last output is because for introduces local scope for last, so after for ends, last from outer scope was used.

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


I did a little digging and this was on purpose under gcc: N3994, terse range-for, which shortly is doing following:

我做了一点挖掘,这是故意在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

then it didn`t make it to c++17 and was removed here:

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

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

#3


0  

according to the standard, a range based for loop is producing the same output as:

根据标准,基于for循环的范围产生相同的输出:

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

As you can see, the iteration variable __begin is being defined in its own scope.

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

Why is last not 99 in the last line?

You have two variables called last. One is in the scope of your main function and holds the value -50. The second variable is defined in the scope of the range based for loop.

你有两个变量叫做last。一个属于主函数的范围并保持值-50。第二个变量在基于循环的范围内定义。

Inside the loop, printing the last variable prints the one from the same scope (ie. from the range based for loop). After the loop however, printing last will again print the variable from the same scope which is the one holding -50

在循环内部,打印最后一个变量打印来自同一范围的变量(即,从基于循环的范围)。然而,在循环之后,打印最后将再次打印来自相同范围的变量,即保持-50的范围

#4


0  

Your program doesn't compile with my g++ 4.9.2.

你的程序不能用我的g ++ 4.9.2编译。

Compile with clang++ 3.5 (with a warning: "range-based for loop with implicit deduced type is a C++1z extension [-Wc++1z-extensions]")

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

But clang++ use different last variables

但clang ++使用不同的最后变量

With the following modified program

用以下修改过的程序

#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;
}

I get the following output

我得到以下输出

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

#1


17  

GCC implemented standards proposal n3994, which suggests that for (elem : range) be syntactic sugar for for (auto&& elem : range). This didn't make it into C++17, so the functionality has been removed from more recent versions of GCC.

海湾合作委员会实施了标准提案n3994,其中(elem:range)表示为(auto && elem:range)的语法糖。这没有进入C ++ 17,因此已从更新版本的GCC中删除了该功能。

The named variable used to iterate over the range must be a declaration according to [stmt.ranged], so your code shouldn't compile.

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

#2


9  

Your code does not compile starting with gcc 6.1 (and for all clang versions):

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

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

it looks like previous versions used auto implicitly here. The fact that you get -50 as last output is because for introduces local scope for last, so after for ends, last from outer scope was used.

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


I did a little digging and this was on purpose under gcc: N3994, terse range-for, which shortly is doing following:

我做了一点挖掘,这是故意在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

then it didn`t make it to c++17 and was removed here:

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

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

#3


0  

according to the standard, a range based for loop is producing the same output as:

根据标准,基于for循环的范围产生相同的输出:

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

As you can see, the iteration variable __begin is being defined in its own scope.

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

Why is last not 99 in the last line?

You have two variables called last. One is in the scope of your main function and holds the value -50. The second variable is defined in the scope of the range based for loop.

你有两个变量叫做last。一个属于主函数的范围并保持值-50。第二个变量在基于循环的范围内定义。

Inside the loop, printing the last variable prints the one from the same scope (ie. from the range based for loop). After the loop however, printing last will again print the variable from the same scope which is the one holding -50

在循环内部,打印最后一个变量打印来自同一范围的变量(即,从基于循环的范围)。然而,在循环之后,打印最后将再次打印来自相同范围的变量,即保持-50的范围

#4


0  

Your program doesn't compile with my g++ 4.9.2.

你的程序不能用我的g ++ 4.9.2编译。

Compile with clang++ 3.5 (with a warning: "range-based for loop with implicit deduced type is a C++1z extension [-Wc++1z-extensions]")

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

But clang++ use different last variables

但clang ++使用不同的最后变量

With the following modified program

用以下修改过的程序

#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;
}

I get the following output

我得到以下输出

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