今天看到关于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

前者处理容器中为指针类型,后者为类类型。




Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐