遍历一个vector容器有非常多种方法。使用起来也是仁者见仁。

通过索引遍历:

  1. for (i = 0; i<v.size(); i++)
  2. {
  3. cout << v[i] << " ";
  4. }

迭代器遍历:

  1. for (vInt::const_iterator iter = v.begin(); iter != v.end();iter++)
  2. {
  3. cout << *iter << " ";
  4. }

算法遍历:

  1. copy(v.begin(), v.end(), ostream_iterator<int>(cout, " "));

非常多书上推荐的是使用算法进行遍历。

写了一个简单的程序对上面的三种方法进行了比較:

  1. #include<iostream>
  2. #include<vector>
  3. #include<iterator>
  4. #include<algorithm>
  5. #include<time.h>
  6. #include<windows.h>
  7. using namespace std;
  8. typedef vector<int> vInt;
  9. void print_vec_operator(const vInt & v)//方法一,採用下标訪问
  10. {
  11. int i;
  12. for (i = 0; i<v.size(); i++)
  13. {
  14. cout << v[i] << " ";
  15. }
  16. cout << endl;
  17. }
  18. void print_vec_iterator(const vInt &v)//方法二,採用迭代器訪问
  19. {
  20. for (vInt::const_iterator iter = v.begin(); iter != v.end();iter++)
  21. {
  22. cout << *iter << " ";
  23. }
  24. cout << endl;
  25. }
  26. void print_vec_algorithm(const vInt &v)//方法三。将容器的内容拷贝到cout绑定的迭代器
  27. {
  28. copy(v.begin(), v.end(), ostream_iterator<int>(cout, " "));
  29. cout << endl;
  30. }
  31. int main()
  32. {
  33. vInt v;
  34. int i;
  35. for (i = 0; i<100000; i++)
  36. {
  37. v.push_back(i);
  38. }
  39. int start_time_print_vec1 = GetTickCount();
  40. print_vec_operator(v);
  41. int end_time_print_vec1 = GetTickCount();
  42. int start_time_print_vec2 = GetTickCount();
  43. print_vec_iterator(v);
  44. int end_time_print_vec2 = GetTickCount();
  45. int start_time_print_vec3 = GetTickCount();
  46. print_vec_algorithm(v);
  47. int end_time_print_vec3 = GetTickCount();
  48. std::cout << (end_time_print_vec1 - start_time_print_vec1) << endl;
  49. std::cout << (end_time_print_vec2 - start_time_print_vec2) << endl;
  50. std::cout << (end_time_print_vec3 - start_time_print_vec3) << endl;
  51. return 0;
  52. }

当vector初始化10000个元素时,三种方法的效率不相上下。执行几次时间相差无几:

//输出:

//1718 operator[]

//1735 iterator

//1797 algorithm

可是当把veector初始化100000的时候,三种方法的效率就有了较大的差距:

//输出:

//20016 operator[]

//32172 iterator

//62468 algorithm

再写一个vector里放一个类:

  1. #include<iostream>
  2. #include<vector>
  3. #include<iterator>
  4. #include <algorithm>
  5. #include <functional>
  6. #include<windows.h>
  7. class AAA
  8. {
  9. public:
  10. void MakeFull2()
  11. {
  12. }
  13. };
  14. int main()
  15. {
  16. int nCount = 1000000;
  17. std::vector< AAA* > vAAA;
  18. vAAA.resize(nCount);
  19. for (int i = 0; i < nCount; ++i)
  20. {
  21. vAAA[i] = new AAA;
  22. }
  23. // 时间
  24. int start, end;
  25. // 測试成员函数调用(std::vector下标訪问方式)
  26. start = GetTickCount();
  27. size_t count = vAAA.size();
  28. for (size_t i = 0; i < count; ++i)
  29. vAAA[i]->MakeFull2();
  30. end = GetTickCount();
  31. std::cout << end - start << std::endl;
  32. // 測试成员函数调用(STL算法方式)
  33. start = GetTickCount();
  34. std::for_each(vAAA.begin(), vAAA.end(),
  35. std::mem_fun<void, AAA>(&AAA::MakeFull2));
  36. end = GetTickCount();
  37. std::cout << end - start << std::endl;
  38. // 測试成员函数调用(STL迭代器方式)
  39. start = GetTickCount();
  40. std::vector< AAA* >::iterator itr_end = vAAA.end();
  41. for (std::vector< AAA* >::iterator itr = vAAA.begin(); itr != itr_end; ++itr)
  42. (*itr)->MakeFull2();
  43. end = GetTickCount();
  44. std::cout << end - start << std::endl;
  45. // 測试成员函数调用(STL迭代器方式)
  46. start = GetTickCount();
  47. for (std::vector< AAA* >::iterator itr = vAAA.begin(); itr != vAAA.end(); ++itr)
  48. (*itr)->MakeFull2();
  49. end = GetTickCount();
  50. std::cout << end - start << std::endl;
  51. return 0;
  52. }
  53. //输出:
  54. //313 oprator[]
  55. //62 algorithm
  56. //422 iterator
  57. //922 iterator

再执行一次,结果为:

//296

//63

//594

//1672

这个时候使用algorithm+functional进行遍历效率最高。

个人认为下标索引的方式总是会效率高于迭代器方式。

以下分析一下两种迭代器方式。为何相差不小呢:

这就要看一下std::vector::end()的原型了:

  1. iterator end() _NOEXCEPT
  2. { // return iterator for end of mutable sequence
  3. return (iterator(this->_Mylast(), &this->_Get_data()));
  4. }

就是每次推断itr != vAAA.end()的时候,都要进行又一次构造一个迭代器并进行返回。这样当然减少的效率。

实战c++中的vector系列--vector的遍历(stl算法、vector迭代器(不要在循环中推断不等于end())、operator[])的更多相关文章

  1. spice在桌面虚拟化中的应用系列之三(USB映射实现,SSL加密,密码认证,多客户端支持)

    本系列其它文章 spice在桌面虚拟化中的应用系列之一(spice简介,性能优化等) spice在桌面虚拟化中的应用系列之二(Linux平台spice客户端的编译安装,支持USB映射) 1.spice ...

  2. 循环中不要放入openSession()

    for(Shop s:list) { System.out.println(s.getName()); String sql="select shopId,sum(ele_bank+ele_ ...

  3. 深入浅出:了解for循环中保留i值得方法

    一.保留i值  通常情况下,因为一些效果我们需要获取到for循环中的i的值,但是往往拿到的都是最后一个i的值.下面介绍几种方法可以获取到i的值 1.自定义属性: arr[i].index = i; 以 ...

  4. 实战c++中的string系列--std:vector 和std:string相互转换(vector to stringstream)

    string.vector 互转 string 转 vector vector  vcBuf;string        stBuf("Hello DaMao!!!");----- ...

  5. 实战c++中的vector系列--vector应用之STL的find、find_if、find_end、find_first_of、find_if_not(C++11)

    使用vector容器,即避免不了进行查找,所以今天就罗列一些stl的find算法应用于vector中. find() Returns an iterator to the first element ...

  6. 实战c++中的vector系列--构造、operator=和assign差别

    vector或许是实际过程中使用最多的stl容器.看似简单,事实上有非常多技巧和陷阱. 着重看一看vector的构造,临时依照C++11: default (1) explicit vector (c ...

  7. 实战c++中的vector系列--正确释放vector的内存(clear(), swap(), shrink_to_fit())

    关于vector已经写的差不多了,似乎要接近尾声了,从初始化到如何添加元素再到copy元素都有所涉及,是时候谈一谈内存的释放了. 是的,对于数据量很小的vector,完全没必要自己进行主动的释放,因为 ...

  8. 实战c++中的vector系列--copy set to vector(别混淆了reserve和resize)

    stl算法中有个copy函数.我们能够轻松的写出这种代码: #include <iostream> #include <algorithm> #include <vect ...

  9. 【实战Java高并发程序设计6】挑战无锁算法:无锁的Vector实现

    [实战Java高并发程序设计 1]Java中的指针:Unsafe类 [实战Java高并发程序设计 2]无锁的对象引用:AtomicReference [实战Java高并发程序设计 3]带有时间戳的对象 ...

随机推荐

  1. 【转】C# client 与java netty 服务端的简单通信,客户端采用Unity

    http://blog.csdn.net/wilsonke/article/details/24721057 近日根据官方提供的通信例子自己写了一个关于Unity(C#)和后台通信的类,拿出来和大家分 ...

  2. puppet实战之master-agent

    author:JevonWei 版权声明:原创作品 blog:http://119.23.52.191/ --- master作为puppet模块的管理者,通过配置各agent节点的配置文件,使age ...

  3. 【bzoj4127】Abs 树链剖分+线段树

    题目描述 给定一棵树,设计数据结构支持以下操作 1 u v d 表示将路径 (u,v) 加d 2 u v 表示询问路径 (u,v) 上点权绝对值的和 输入 第一行两个整数n和m,表示结点个数和操作数 ...

  4. mysql里制造一个错误

    最近突然想到的,由于在触发器中执行失败事务性表会自动回滚. 所以就想制造一个错误,在群里问了问最后还真得到一个制造错误的方法,或者可以叫做自定义异常 SIGNAL SQLSTATE ' SET MES ...

  5. WF 18 A 想法

    UPD:我理解错题意了. 考虑在时刻 $t$ 从站点 $u$ 出发的公交车,将这些车的集合记做 $B(u,t)$,$B(u,t)$ 是个随机变量. 令 $\mathrm{Pr}_{B(u,t)} = ...

  6. 洛谷P3832 [NOI2017]蚯蚓排队 【链表 + 字符串hash】

    题目链接 洛谷P3832 题解 字符串哈希然后丢到hash表里边查询即可 因为\(k \le 50\),1.2操作就暴力维护一下 经复杂度分析会发现直接这样暴力维护是对的 一开始自然溢出WA了,还以为 ...

  7. linux系统程序设计教程

    linux系统程序设计教程 第一章:生成一个Process(进程) 进程是什么?简单地说,进程就是在执行状态下的一个程序(包括CPU状态,所占内存的状态,等等) A进程生成了B进程,也就是说,A程序在 ...

  8. vmware虚拟机无法ping通主机,也无法联网

  9. mac 常用操作

    1. 快速获取文件夹的位置: 打开文本 terminal 程序,将文件拖进去,路径会自己主动打印出来 2. 移动文件夹: 选中目标文件,然后使用 Command+C 复制,然后用 Command +O ...

  10. 微信小程序 报警告的解决办法

    wx:for   如果没有给它相应的  wx:key 控制台就会有警告,解决的办法给它添加相应的key警告就消失啦