在 c++ 中,基于范围的 for 循环将保留索引顺序

Will range based for loop in c++ preserve the index order

本文关键字:循环 for 保留 顺序 索引 范围 c++ 于范围      更新时间:2023-10-16

在 c++11 中,如果我使用基于 for 循环的范围,它会保证迭代顺序吗?

即以下代码块是否保证产生相同的输出?

vector<T> output;
vector<U> V;
for( auto v: V) output.push_back(f(v));

for(int i =0; i < V.size(); ++i) output.push_back(f(V[i])); 

如果不是vector而是map等等怎么办?

是的,保证这两个代码做同样的事情。虽然我没有标准的链接,但你可以看看这里。我引用:You can read that as "for all x in v" going through starting with v.begin() and iterating to v.end().

是的,它们是等效的。 6.5.4 中的标准保证:

对于表单的基于范围的 for 语句

for ( for-range-declaration : expression ) statement

range-init等效于用括号括起来的表达式(表达式(

以及基于范围的 for 表单语句

for ( for-range-declaration : braced-init-list ) statement

range-init等效于大括号初始化列表。在每种情况下,基于范围的 for 语句等效于

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

其中 __range__begin__end 是仅为表达式定义的变量,_RangeT 是表达式的类型,begin-exprend-expr

确定如下:

— 如果_RangeT是数组类型,则begin-exprend-expr分别是__range__range + __bound,其中__bound是数组绑定。如果_RangeT是未知大小的数组或不完整类型的数组,则程序格式不正确;

— 如果_RangeT是类类型,则在类 _RangeT 的范围内查找非限定 ID beginend 好像通过类成员访问查找 (3.4.5(,如果其中一个(或两个(找到至少一个声明,则分别__range.begin()end-expr begin-expr__range.end();

— 否则,begin-exprend-expr 分别是begin(__range)end(__range),其中beginend使用依赖于参数的查找进行查找 (3.4.2(。出于此名称查找的目的,命名空间std是关联的命名空间。

虽然你关于地图的问题有点荒谬。 如果它是一个有序映射,并且您正确地遍历了映射,那么它们是等效的。 如果它是一个无序地图,那么你的问题就没有多大意义了。

是和否(这取决于使用的容器(:

  • 基于 for 的范围是一个循环,例如 for(迭代器 pos = range.begin((; pos !=range.end((;++pos( {/* 带有范围变量 = *pos */... }
  • 运算符 [] 可能会执行不同操作(例如,如果键不存在,则 std::map 运算符对键进行查找并创建一个新条目(

例:

#include <iostream>
#include <map>
int main()
{
    typedef std::map<int, int> map;
    map m = { { 0, 0 }, { 2, 2 }, { 4, 4 } };
    for(const auto& e : m) {
        std::cout << e.first << " ";
    }
    std::cout << std::endl;
    for(map::size_type i = 0; i < m.size(); ++i) {
        std::cout << m[i] << " ";
    }
    std::cout << std::endl;
    return 0;
}

结果是:

0 2 4 
0 0 2 0 4 

(第二个结果可能是在自己的脚上射得好,甚至是有意的(