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

时间:2013-09-27 13:28:53

标签: c++ c++11

在c ++ 11中,如果我在向量上使用基于范围的循环,它会保证迭代顺序吗? 比方说,对于相同的输出,是否可以保证以下代码块?

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

vs

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

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

3 个答案:

答案 0 :(得分:15)

是的,这两个代码保证会这样做。虽然我没有指向标准的链接,但您可以查看here。我引述:You can read that as "for all x in v" going through starting with v.begin() and iterating to v.end().

答案 1 :(得分:13)

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

  

对于基于范围的表格形式

     

for(for-range-declaration:expression)statement

     

让range-init等同于括号(表达式)

所包围的表达式      

以及表单

的基于范围的for语句      

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

     

让range-init等同于braced-init-list。在每种情况下,基于范围的for语句等同于

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

其中__range,__ begin和__end是仅为exposition定义的变量,_RangeT是表达式的类型,begin-expr和end-expr确定如下:   表达式,begin-expr和end-expr确定如下:

     

- 如果_RangeT是一个数组类型,则begin-expr和end-expr分别是__range和__range + __bound,其中__bound是数组绑定的。如果_RangeT是一个未知大小的数组或一个类型不完整的数组,那么该程序就是格式不正确的;

     

- 如果_RangeT是类类型,则在类_RangeT的范围内查找unqualified-ids的开始和结束   好像通过类成员访问查找(3.4.5),如果其中任何一个(或两者)找到至少一个声明,开始 -   expr和end-expr分别是__range.begin()和__range.end();

     

- 否则,begin-expr和end-expr分别是begin(_ range)和end( _range),其中begin和end用参数依赖查找查找(3.4.2) )。出于此名称查找的目的,namespace std是一个关联的命名空间。

虽然你对地图的问题有点荒谬。如果它是一个有序的地图,你正确地迭代地图,那么它们是等价的。如果这是一张无序的地图,那么你的问题并没有多大意义。

答案 2 :(得分:10)

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

  • 基于for的范围是类似于(iterator 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 

(第二个结果可能是一个很好的镜头,甚至是自己的意图)