天马阁

 找回密码
 立即注册
                                        →→→→→→→→→→→→ 1点击查看所有VIP教程目录长列表(总教程数269个) 2办理VIP详情进入 ←←←←←←←←←←←←
1 x64CE与x64dbg入门基础教程 7课 已完结 2 x64汇编语言基础教程 16课 已完结 3 x64辅助入门基础教程 9课 已完结 4 C++x64内存辅助实战技术教程 149课 已完结
5 C++x64内存检测与过检测技术教程 10课 已完结 6 C+x64二叉树分析遍历与LUA自动登陆教程 19课已完结 7 C++BT功能原理与x64实战教程 29课 已完结 8 C+FPS框透视与自瞄x64实现原理及防护思路 30课完结
64驱?封? 9 64反驱? 10 64位V? 11 绝? 12 ???课?
13 64透 ? 14 64U ? 15 64Q ? 16 64功 ?
17 64U ? 18 64模 ? 19 64多 ? 20 64网 ?
21 64注 ? 22 64火 ? 23 64棋 ? 24 64自二链L?
25 64破 ? VIP会员办理QQ: 89986068   
【请先加好友,然后到好友列表双击联系客服办理,不然可能无法接受到信息。】
27 加入2000人交流群637034024 3 28 免责声明?
查看: 4652|回复: 0

std::vector的几种遍历方式比较

[复制链接]

10

主题

0

回帖

12

积分

编程入门

Rank: 1

天马币
20
发表于 2024-3-1 14:00:02 | 显示全部楼层 |阅读模式

std::vector是我在标准库中实用最频繁的容器。总结一下在遍历和创建vector时需要注意的一些地方。

在不考虑线程安全问题的前提下,在C++11中有五种遍历方式。

方式一

for (size_t i =0; i < vec.size(); i ++) {

        int d = vec;

        }

方式二

size_t len = vec.size();

    for (size_t i =0; i < len; i ++) {

        int d = vec;

    }

方式三
for (auto it = vec.begin(); it != vec.end(); it ++) {

        int d = *it;

    }

方式四
for (int i:vec) {

        int d = i;

    }


方式五

    for_each(vec.begin(), vec.end(), [](int i){

        int d = i;

    });


代码很简单,如果不实际测试的话。你能推测出哪种方式效率最高吗?
我在mac下面用xcode测试了这五种遍历方式。

////h文件

void testBianli();

void testBianli1(conststd::vector<int>& vec);

void testBianli2(conststd::vector<int>& vec);

void testBianli3(conststd::vector<int>& vec);

void testBianli4(const std::vector<int>& vec);

void testBianli5(const std::vector<int>& vec);
////end h文件

///cpp文件

void testBianli()

{


size_t counter = 1000000;

    std::vector<int> vec(counter);

    testBianli1(vec);

    testBianli2(vec);

    testBianli3(vec);

   testBianli4(vec);

testBianli5(vec);


}

void  testBianli1(conststd::vector<int>& vec)

{

    MEARSURE_DURATION(all);

    for (size_t i =0; i < vec.size(); i ++) {

        int d = vec;

    }

}

void  testBianli2(conststd::vector<int>& vec)

{

    MEARSURE_DURATION(all);

    size_t len = vec.size();

    for (size_t i =0; i < len; i ++) {

        int d = vec;

    }

}

void testBianli3(conststd::vector<int>& vec)

{

    MEARSURE_DURATION(all);

    for (auto it = vec.begin(); it != vec.end(); it ++) {

        int d = *it;

    }

}

void testBianli4(conststd::vector<int>& vec)

{

    MEARSURE_DURATION(all);

    for (int i:vec) {

        int d = i;

    }

}

void testBianli5(conststd::vector<int>& vec)

{

    MEARSURE_DURATION(all);

    for_each(vec.begin(), vec.end(), [](int i){

        int d = i;

    });

}


其中需要定义一个测试函数运行时间的类和一个宏

#define MEARSURE_DURATION(fun) CFunctionDuration fun(std::string(std::string(__FUNCTION__) +" " +std::string(#fun)).c_str() );

class CFunctionDuration {

   

public:

    CFunctionDuration(const char* funname)

    {

        m_start_df = clock();

        sprintf(m_funname,"%s",funname);

    }

    ~CFunctionDuration()

    {

        double du = (clock() -m_start_df)*0.001;

        if (du >= 0) {

            printf("%s running duration:%f(ms) \n",m_funname,du);

        }

    }

   

private:

    double m_start_df;

    char m_funname[256];

};

最后输出结果如下:

testBianli1 all running duration:3.440000(ms)

testBianli2 all running duration:2.854000(ms)

testBianli3 all running duration:11.009000(ms)

testBianli4 all running duration:5.109000(ms)

testBianli5 all running duration:7.637000(ms)


很明显了,第二种方式是最快的。个人觉得原因如下:
第一种方法每次都要调用size()函数去计算vec的长度。通过查看size(),其实现如下:

_LIBCPP_INLINE_VISIBILITY

size_type size() const_NOEXCEPT

{return static_cast<size_type>(this->__end_ -this->__begin_);}

指针地址相减,再来一个强制转换最后得到size()。就这这里稍微费点时间。

第三种方式是最费时间的。使用迭代器it循环,迭代器本身不是内部数据,它的各种操作(比较,偏移,取值操作)都是一系列内联函数操作,暗地里干的事远比看到的复杂。这个迭代器给自己套上伪装,让你可以像使用指针一样利用它去访问对象,但是毕竟中间隔了一层。个人觉得迭代器的实用主要是便于stl中算法的实现,有一种通用的数据类型来访问各种容器中的元素。

第四种方式从形式上看非常简洁,可干活却没有长相利索。这是C++11的新特性。

第五种方式也是c++的新特性。其中包括大受推崇的lambda特性。这种特性是向其它语言学习的结果。在这里也跑的不是最快的。

其实这些运行时间结果的差别也只有在遍历过程中对元素操作的过程很简短的时候才会显现出来。当对每个元素操作花费的时间跟纯粹遍历vector所费时间不是一个数量级时,这些区别就不重要了。另外这个时间在不同设备上运行的时间肯定是不一样的。不同编译器下得到的结果也不一样,但是其相对运行效率还是有参考意义的。

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

天马阁|C/C++辅助教程|安卓逆向安全| 论坛导航|免责申明|Archiver||网站地图
拒绝任何人以任何形式在本论坛发表与中华人民共和国法律相抵触的言论,本站内容均为会员发表,并不代表天马阁立场!
任何人不得以任何方式翻录、盗版或出售本站视频,一经发现我们将追究其相关责任!
我们一直在努力成为最好的编程论坛!
Copyright© 2010-2021 All Right Reserved.
快速回复 返回顶部 返回列表