vector的遍历(stl算法、vector迭代器(不要在循环中判断不等于end())、operator[])

最后更新于:2022-04-01 06:44:26

## 实战c++中的vector系列--vector的遍历(stl算法、vector迭代器(不要在循环中判断不等于end())、operator[]) 遍历一个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()的时候,都要进行重新构造一个迭代器并进行返回,这样当然降低的效率。
';