1. 程式人生 > >C++11中對容器的各種循環遍歷的效率比較

C++11中對容器的各種循環遍歷的效率比較

ets normal pre unsigned int qdebug tex contain string

  1 #include "CycleTimeTst.h"
  2 #include <string>
  3 #include <vector>
  4 #include <list>
  5 #include <limits>
  6 #include <assert.h>
  7 #include <QTime>
  8 #include <QDebug>
  9 
 10 class TimeUsedGuard
 11 {
 12 public:
 13     TimeUsedGuard(const std::string
& msg) 14 : m_msg(msg) 15 , m_time(QTime::currentTime()) 16 { 17 } 18 ~TimeUsedGuard() 19 { 20 qDebug() << m_msg.c_str() << "use time:" << m_time.elapsed() << "ms"; 21 } 22 23 private: 24 std::string m_msg; 25
QTime m_time; 26 }; 27 28 template <typename T> 29 T useData(T val) 30 { 31 return std::sqrt(val); 32 } 33 34 template <typename _Container> 35 void normalForLoop(const _Container& datas) 36 { 37 TimeUsedGuard timeUsedGuard(__FUNCTION__); 38 size_t i = 0
; 39 for (; i < datas.size(); ++i) 40 { 41 useData(datas[i]); 42 } 43 } 44 45 template <typename _Container> 46 void normalForLoopCallSizeOnce(const _Container& datas) 47 { 48 TimeUsedGuard timeUsedGuard(__FUNCTION__); 49 size_t i = 0; 50 size_t size = datas.size(); 51 for (; i < size; ++i) 52 { 53 useData(datas[i]); 54 } 55 } 56 57 template <typename _Container> 58 void iterator(const _Container& datas) 59 { 60 TimeUsedGuard timeUsedGuard(__FUNCTION__); 61 auto pos = datas.cbegin(); 62 for (; pos != datas.cend(); ++pos) 63 { 64 useData(*pos); 65 } 66 } 67 68 template <typename _Container> 69 void iteratorCallCEndOnce(const _Container& datas) 70 { 71 TimeUsedGuard timeUsedGuard(__FUNCTION__); 72 auto pos = datas.cbegin(); 73 auto end = datas.cend(); 74 for (; pos != end; ++pos) 75 { 76 useData(*pos); 77 } 78 } 79 80 template <typename _Container> 81 void qtForeach(const _Container& datas) 82 { 83 TimeUsedGuard timeUsedGuard(__FUNCTION__); 84 foreach (auto data, datas) 85 { 86 useData(data); 87 } 88 } 89 90 template <typename _Container> 91 void stdForeach(const _Container& datas) 92 { 93 TimeUsedGuard timeUsedGuard(__FUNCTION__); 94 std::for_each(datas.cbegin(), datas.cend(), useData<typename _Container::value_type>); 95 } 96 97 template <typename _Container> 98 void rangeForLoop(const _Container& datas) 99 { 100 TimeUsedGuard timeUsedGuard(__FUNCTION__); 101 for (auto data : datas) 102 { 103 useData(data); 104 } 105 } 106 107 template <typename _Container> 108 void rangeForLoopReference(const _Container& datas) 109 { 110 TimeUsedGuard timeUsedGuard(__FUNCTION__); 111 for (auto& data : datas) 112 { 113 useData(data); 114 } 115 } 116 117 class CycleTimeTst 118 { 119 public: 120 CycleTimeTst(); 121 }; 122 123 CycleTimeTst g_CycleTimeTst; 124 CycleTimeTst::CycleTimeTst() 125 { 126 constexpr unsigned long MAX_AMOUNT = 100 * 1000 * 1000; 127 128 // std::vector<int> datas; 129 // for (unsigned long i = 1; i < MAX_AMOUNT; ++i) 130 // { 131 // datas.push_back(i); 132 // } 133 std::list<double> datas; 134 double d = 1.0; 135 for (unsigned long i = 1; i < MAX_AMOUNT / 10; ++i) 136 { 137 datas.push_back(d); 138 } 139 140 // normalForLoop(datas); 141 // normalForLoopCallSizeOnce(datas); 142 iterator(datas); 143 iteratorCallCEndOnce(datas); 144 qtForeach(datas); 145 stdForeach(datas); 146 rangeForLoop(datas); 147 rangeForLoopReference(datas); 148 // vector<int> 100 * 1000 * 1000 times, debug & release: 149 // normalForLoop use time: 1096 ms normalForLoop use time: 113 ms 150 // normalForLoopCallSizeOnce use time: 926 ms normalForLoopCallSizeOnce use time: 106 ms 151 // iterator use time: 1941 ms iterator use time: 103 ms 152 // iteratorCallCEndOnce use time: 1473 ms iteratorCallCEndOnce use time: 101 ms 153 // qtForeach use time: 1846 ms qtForeach use time: 262 ms 154 // stdForeach use time: 1488 ms stdForeach use time: 120 ms 155 // rangeForLoop use time: 1527 ms rangeForLoop use time: 101 ms 156 // rangeForLoopReference use time: 1551 ms rangeForLoopReference use time: 102 ms 157 158 // list<double> 10 * 1000 * 1000 times, debug & release: 159 // iterator use time: 206 ms iterator use time: 27 ms 160 // iteratorCallCEndOnce use time: 183 ms iteratorCallCEndOnce use time: 26 ms 161 // qtForeach use time: 1493 ms qtForeach use time: 743 ms 162 // stdForeach use time: 182 ms stdForeach use time: 27 ms 163 // rangeForLoop use time: 186 ms rangeForLoop use time: 26 ms 164 // rangeForLoopReference use time: 186 ms rangeForLoopReference use time: 27 ms 165 }

個人總結:

vector支持隨機訪問,但無通用性,當采用list後,就不能再使用了,不可取.

叠代器與範圍for循環所用時間無明顯差異, qt提供的foreach顯然是最差的方法, std算法for_each也還可以接受, 但範圍for循環好看得多, 更好用啊!

在循環中調用調用cend方法,會頻繁創建一個新的叠代器(不停的構造與析構),另外還有函數調用開銷,在debug版本結果來看似乎確實有一定的影響,但在realease版本下所花時間幾乎相等,也許編譯器有優化吧!

C++11中對容器的各種循環遍歷的效率比較