实战c++中的vector系列--vector的遍历(stl算法、vector迭代器(不要在循环中判断不等于end())、operator[])

来源:互联网 发布:seo关键词怎么分 编辑:程序博客网 时间:2024/06/09 00:00

遍历一个vector容器有很多种方法,使用起来也是仁者见仁。

通过索引遍历:

for (i = 0; i<v.size(); i++){    cout << v[i] << " ";}

迭代器遍历:

for (vInt::const_iterator iter = v.begin(); iter != v.end();iter++){    cout << *iter << " ";}

算法遍历:

copy(v.begin(), v.end(), ostream_iterator<int>(cout, " "));

很多书上推荐的是使用算法进行遍历。写了一个简单的程序对上面的三种方法进行了比较:

#include<iostream>#include<vector>#include<iterator>#include<algorithm>#include<time.h>#include<windows.h>using namespace std;typedef vector<int> vInt;void print_vec_operator(const vInt & v)//方法一,采用下标访问{    int i;    for (i = 0; i<v.size(); i++)    {        cout << v[i] << " ";    }    cout << endl;}void print_vec_iterator(const vInt &v)//方法二,采用迭代器访问{    for (vInt::const_iterator iter = v.begin(); iter != v.end();iter++)    {        cout << *iter << " ";    }    cout << endl;}void print_vec_algorithm(const vInt &v)//方法三,将容器的内容复制到cout绑定的迭代器{    copy(v.begin(), v.end(), ostream_iterator<int>(cout, " "));    cout << endl;}int main(){    vInt v;    int i;    for (i = 0; i<100000; i++)    {        v.push_back(i);    }    int start_time_print_vec1 = GetTickCount();    print_vec_operator(v);    int end_time_print_vec1 = GetTickCount();    int start_time_print_vec2 = GetTickCount();    print_vec_iterator(v);    int end_time_print_vec2 = GetTickCount();    int start_time_print_vec3 = GetTickCount();    print_vec_algorithm(v);    int end_time_print_vec3 = GetTickCount();    std::cout << (end_time_print_vec1 - start_time_print_vec1) << endl;    std::cout << (end_time_print_vec2 - start_time_print_vec2) << endl;    std::cout << (end_time_print_vec3 - start_time_print_vec3) << endl;    return 0;}

当vector初始化10000个元素时,三种方法的效率不相上下,运行几次时间相差无几:
//输出:
//1718 operator[]
//1735 iterator
//1797 algorithm

但是当把veector初始化100000的时候,三种方法的效率就有了较大的差距:
//输出:
//20016 operator[]
//32172 iterator
//62468 algorithm

再写一个vector里放一个类:

#include<iostream>#include<vector>#include<iterator>#include <algorithm>#include <functional>#include<windows.h>class AAA{public:    void MakeFull2()    {    }};int main(){    int nCount = 1000000;    std::vector< AAA* > vAAA;    vAAA.resize(nCount);    for (int i = 0; i < nCount; ++i)    {        vAAA[i] = new AAA;    }    // 时间    int start, end;    // 测试成员函数调用(std::vector下标访问方式)    start = GetTickCount();    size_t count = vAAA.size();    for (size_t i = 0; i < count; ++i)        vAAA[i]->MakeFull2();    end = GetTickCount();    std::cout << end - start << std::endl;    // 测试成员函数调用(STL算法方式)    start = GetTickCount();    std::for_each(vAAA.begin(), vAAA.end(),        std::mem_fun<void, AAA>(&AAA::MakeFull2));    end = GetTickCount();    std::cout << end - start << std::endl;    // 测试成员函数调用(STL迭代器方式)    start = GetTickCount();    std::vector< AAA* >::iterator itr_end = vAAA.end();    for (std::vector< AAA* >::iterator itr = vAAA.begin(); itr != itr_end; ++itr)        (*itr)->MakeFull2();    end = GetTickCount();    std::cout << end - start << std::endl;    // 测试成员函数调用(STL迭代器方式)    start = GetTickCount();    for (std::vector< AAA* >::iterator itr = vAAA.begin(); itr != vAAA.end(); ++itr)        (*itr)->MakeFull2();    end = GetTickCount();    std::cout << end - start << std::endl;    return 0;}//输出://313 oprator[]//62  algorithm//422 iterator//922  iterator

再运行一次,结果为:
//296
//63
//594
//1672

这个时候使用algorithm+functional进行遍历效率最高。
个人觉得下标索引的方式总是会效率高于迭代器方式。

下面分析一下两种迭代器方式,为何相差不小呢:

这就要看一下std::vector::end()的原型了:

iterator end() _NOEXCEPT{   // return iterator for end of mutable sequence    return (iterator(this->_Mylast(), &this->_Get_data()));}

就是每次判断itr != vAAA.end()的时候,都要进行重新构造一个迭代器并进行返回,这样当然降低的效率。

2 0
原创粉丝点击