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

aha*_*ala 17 c++ c++11

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

vector<T> output;
vector<U> V;
for( auto v: V) output.push_back(f(v));
Run Code Online (Sandbox Code Playgroud)

VS

for(int i =0; i < V.size(); ++i) output.push_back(f(V[i])); 
Run Code Online (Sandbox Code Playgroud)

如果它是什么不是vector,但map等?

izo*_*ica 18

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


Omn*_*ity 15

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

对于基于范围的表单声明

for(range-declaration:expression)语句

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

以及基于范围的表格声明

for(range-declaration:braced-init-list)语句

让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
  }
}
Run Code Online (Sandbox Code Playgroud)

其中__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)一样,并且如果其中任何一个(或两者)找到至少一个声明, begin-expr和end-expr分别是__range.begin()和__range.end();

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

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


小智 10

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

  • 基于for的范围是一个循环,如(iterator pos = range.begin(); pos!= range.end(); ++ pos){/*with range variable =*pos*/...}
  • operator []可能会做一些不同的事情(例如,如果密钥不存在,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;
}
Run Code Online (Sandbox Code Playgroud)

结果是:

0 2 4 
0 0 2 0 4 
Run Code Online (Sandbox Code Playgroud)

(第二个结果可能是自己的脚或甚至打算很好的射击)

  • 你可能应该指出,在这个例子中,用户正在做一些可怕的错误.如果在带有keytype`int`的`map`上有顺序索引,那么你不应该使用`map`,你应该使用`deque`或`vector`或`array`.如果你没有顺序索引,那么你应该使用迭代器进行迭代,而不是使用`for(int i = 0; i <blah; ++ i) (4认同)