C++11中對容器的各種循環遍歷的效率比較
阿新 • • 發佈:2017-06-30
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; 25QTime 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中對容器的各種循環遍歷的效率比較