24

在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])); 

如果不是vectorbutmap等怎么办?

4

3 回答 3

24

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

于 2013-09-27T13:31:07.497 回答
22

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

对于形式的基于范围的 for 语句

for ( for-range-declaration : expression ) statement

letrange-init等价于括号括起来的表达式 ( expression )

和基于范围的 for 形式的声明

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

letrange-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确定如下:

— if_RangeT是一个数组类型,begin-expr并且end-expr分别是__range__range + __bound__bound数组绑定在哪里。如果_RangeT是一个未知大小的数组或一个不完整类型的数组,则程序是非良构的;

— 如果_RangeT是类类型,则在类范围内查找非限定 IDbegin和 ,就像通过类成员访问查找 (3.4.5) 一样,并且如果其中一个(或两者)找到至少一个声明,并且是和,分别;end_RangeTbegin-exprend-expr__range.begin()__range.end()

— 否则,begin-exprend-exprbegin(__range)end(__range),分别在哪里beginend用依赖于参数的查找(3.4.2)进行查找。出于此名称查找的目的,命名空间std是一个关联的命名空间。

尽管您关于地图的问题有点荒谬。如果它是有序地图并且您正确地遍历地图,那么它们是等价的。如果它是一个无序的地图,那么你的问题并没有多大意义。

于 2013-09-27T13:40:08.660 回答
10

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

  • 基于范围的 for 是一个循环,例如 for(iterator pos = range.begin(); pos != range.end(); ++pos) { /* with a range variable = *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 

(第二个结果可能是一脚好球,甚至是故意的)

于 2013-09-27T13:39:21.390 回答