在编程过程中,经常都会遇到需要建一个大的vector,并对里面的元素一一顺序求值。此时我们有两种选择
先reserve(n)后,再一一的push_back
先建立含n元素的vector,再一一的通过下标为其赋值
那么,这两个方法哪个会更快一些呢?
方法1的好处是再分配内存时直接预留较大的内存即可,而方法2,在建立vector中时,要对其元素一一赋值。
方法2每次直接下标调用即可,不需像方法1每次通过push_back函数为其赋值。
为此,笔者作了如下实验
test1:
int main() {
int i=100000;
for(int j=0;j< i;j++){
vector<int> sz;
sz.reserve(10000);
for(int k=0;k<10000;k++)
sz.push_back(1);
}
return 0;
}
test2:
int main() {
int i=100000;
for(int j=0;j<i;j++){
vector<int> sz(10000);
for(int k=0;k<10000;k++)
sz[k]=1;
}
return 0;
}
用g++编译后,在ubuntu上测试两个程序的运行时间,发现test1需要20.289s,而test2竟只需要5.435s。且更换数据,多次均是如此。
由此,显然可知,先建立n个元素的vector,再一一用下标取值要快的多。 与n次push_back的时间相比,遍历vector为每个元素的初始化所花时间完全是微不足道的。
故,在已知vector的数据的时候,直接在声明时给出元素个数,是十分明智且效率高的选择。在数据存取时,在同等情况下,可尽量用数组下标存取元素,减少调用push_back的次数。
plus,原因浅究
为什么vector会造成这么慢的访问速度呢?查阅stl源码,发现push_back调用了insert_aux,并在此函数中调用了constructor,copy_backward等函数,其函数的功能也都较简单,但其每一步都要检查是否有效是否发生错误等情况,可见其主要是频繁的检查与其他函数的调用占用了时间,(在调用函数的时候,会需要保留栈,保存变量等情况,在大量push_back时,这些也无形中占用了许多时间,也自然堆积起来使得程序2比程序1慢很多)。