今天看到关于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
前者处理容器中为指针类型,后者为类类型。