遍历C++中vector,可以通过下标或者iterator,后者看起来似乎比前者更高级点,所以喜欢装B的程序员应该比较倾向后者。但是真正效率如何呢?
下面是在VS2005里写的一段测试代码,由于这个机房的环境,只能用这个编译器,其他编译器没有测。
// testVector.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <vector>
#include <windows.h>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
vector<long> v;
int n = 1000000;
for(int i = 0 ; i < n ; i++){
v.push_back(i);
}
int k;
vector<long>::iterator beg = v.begin();
vector<long>::iterator end = v.end();
int t1 = GetTickCount();
for(int i = 0 ; i < n ; i++){
k = v[i];
}
int t2 = GetTickCount();
for(vector<long>::iterator i = beg ; i != end ; ++i){
k = *i;
}
int t3 = GetTickCount();
printf("%d %d\n", t2 - t1, t3 - t2);
return 0;
}
测试结果:110 234
后一种访问方式是前一种的2倍,但都还在一个数量级上。
所以vector的随机访问还是很快的。
这里需要注意几点:
用iterator时 ,最好把vector里的end提取出来,而不是写成下面这个样子:
for(vector<long>::iterator i = v.begin() ; i != v.end() ; ++i){
k = *i;
}
因为v.end()也是一个非常耗时的操作,写成这个样子运行后输出是800左右。不过v.size()这个操作并不是很费时,所以第一种里for的判断条件写成i<v.size()也不会带来太大负担。
另外用iterator时,循环里i增加的操作应该写成++i,而不是i++。
先加后用和先用后加都只是从表现形式上说的,实现的流程并不是这样。两个的实现是一个相同的函数,只不过返回值不同,一个是返回更改前的一个拷贝,一个返回的是更改后的引用。
而拷贝的过程显然比引用来的费时。
写成i++后,运行后输出是1700左右,大了一个数量级。
i是int等基本类型时,i++和++i并没有明显速度上的区别。
综上所述,利用下标访问即快又方便。。。java里的ArrayList也是个坑爹的货,for each比get慢得多。