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版本下所花时间几乎相等,也许编译器有优化吧!

posted @ 2017-06-29 23:12  阿Hai  阅读(8276)  评论(0编辑  收藏  举报