C++11中对容器的各种循环遍历的效率比较
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版本下所花时间几乎相等,也许编译器有优化吧!
代码养活自己