今天看到关于vector遍历效率问题,以前遍历的时候却没有关心这些,实为惭愧。自己写了点代码放在vs2012上运行,得到结果和原来的博客上内容不符合。看来应该还有与平台和编译器优化有关。
代码如下:
#include "stdafx.h" #include <vector> #include <algorithm> #include <functional> #include <iostream> int _tmain(int argc, _TCHAR* argv[]) { class CTest { public: void add(){} }; typedef std::vector<CTest*> VEC; VEC::size_type nAmount = 1000000; std::vector<CTest*> vec; vec.resize(nAmount); for (VEC::size_type i = 0; i < nAmount; ++i) { vec[i] = new CTest(); } DWORD dwStart, dwEnd; // STL -- for_each dwStart = timeGetTime(); std::for_each(vec.begin(), vec.end(), std::mem_fun<void, CTest>(&CTest::add)); dwEnd = timeGetTime(); std::cout << "for_each:\t" << dwEnd - dwStart << std::endl; // STL -- iterator dwStart = timeGetTime(); std::vector<CTest*>::iterator itr_begin = vec.begin(); std::vector<CTest*>::iterator itr_end = vec.end(); for (; itr_begin != itr_end; ++itr_begin) { (*itr_begin)->add(); } dwEnd = timeGetTime(); std::cout << "iterator:\t" << dwEnd - dwStart << std::endl; // STL -- iterator2 dwStart = timeGetTime(); std::vector<CTest*>::iterator itr_begin2 = vec.begin(); for (; itr_begin2 != vec.end(); ++itr_begin2) { (*itr_begin2)->add(); } dwEnd = timeGetTime(); std::cout << "iterator:\t" << dwEnd - dwStart << std::endl; // operator[] dwStart = timeGetTime(); for (size_t i = 0; i < nAmount; ++i) { vec[i]->add(); } dwEnd = timeGetTime(); std::cout << "operator:\t" << dwEnd - dwStart << std::endl; system("pause"); return 0; }
测试多次,结果相差不大,截图三张:
结果表明,使用迭代器效果最差,使用STL算法和下标方式差不多。
1、for_each (vs2012版)
template<class _InIt, class _Fn1> inline _Fn1 for_each(_InIt _First, _InIt _Last, _Fn1 _Func) { // perform function for each element _DEBUG_RANGE(_First, _Last); _DEBUG_POINTER(_Func); _For_each(_Unchecked(_First), _Unchecked(_Last), _Func); return (_STD move(_Func)); }
2、end() (vs2012版)
iterator end() _NOEXCEPT { // return iterator for end of mutable sequence return (iterator(this->_Mylast, this)); }
3、operator[] (vs2012版)
const_reference operator[](size_type _Pos) const { // subscript nonmutable sequence #if _ITERATOR_DEBUG_LEVEL == 2 if (size() <= _Pos) { // report error _DEBUG_ERROR("vector subscript out of range"); _SCL_SECURE_OUT_OF_RANGE; } #elif _ITERATOR_DEBUG_LEVEL == 1 _SCL_SECURE_VALIDATE_RANGE(_Pos < size()); #endif /* _ITERATOR_DEBUG_LEVEL */ return (*(this->_Myfirst + _Pos)); }
特别的注意点是end(),每次调用end()就重新构建一个对象。第三种方法几乎是第二种的两倍。
===================================================
mem_fun和mem_fun_ref
前者处理容器中为指针类型,后者为类类型。