zoukankan      html  css  js  c++  java
  • 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版本下所花时间几乎相等,也许编译器有优化吧!

  • 相关阅读:
    谷歌地图地理解析和反解析geocode.geocoder详解(转)
    Html5 Geolocation获取地理位置信息(转)
    利用单片机快速实现家庭智能控制平台
    邪恶改装:TPYBoard制作廉价WIFI干扰器
    [TPYBoard
    [TPYBoard
    [TPYBoard
    python中的subprocess.Popen()使用
    KVM虚拟机的xml配置文件
    Linux LVM 总结
  • 原文地址:https://www.cnblogs.com/diysoul/p/7096795.html
Copyright © 2011-2022 走看看