附加代码包含对std :: vector :: assign()的三次调用。在第一次调用之前,调用std :: vector :: reserve()来分配适当的内存量,然后填充向量。第二次调用assign()在填充第二个向量之前不调用reserve(),所以我希望在调用assign()期间至少有一个分配。对assign()的第三次调用用于使用新数据重新填充第一个向量。代码中的第四个块使用new分配一个int数组并填充它。
我希望第一,第三和第四个块的性能相同,而第二个块由于所需的分配需要额外的时间。我实际发现的是,第一个和第二个块占用相同的时间,第三个和第四个块的运行速度明显更快(~30%)。在我看来,对reserve()的调用实际上并没有分配所需的空间,但是在调用assign()之前,分配被推迟。
我在两个平台上测试了这个:使用Visual C ++ 2010编译器编译的Windows Vista和使用gcc 4.3.2编译器的SUSE linux。我尝试了不同级别的优化(包括没有优化),并继续看到相同的行为。任何想法为什么保留()没有做我期望的?如果我所看到的是正确的行为,那么保留()的重点是什么?
谢谢, 约什
#include <vector>
#include <time.h>
#include <stdio.h>
#include <iostream>
int main()
{
int len=1E8, nloops=100;
clock_t start, stop;
double wr=0.0, wor=0.0, wc=0.0, pb=0.0;
printf("Number of values tested = %d\n", len);
printf("Number of loops = %d\n", nloops);
std::vector<int> vec1a, vec1b;
for(int i=0; i<len; i++) vec1a.push_back(i);
for(int i=len; i>0; i--) vec1b.push_back(i);
for(int i=0; i<nloops; i++)
{
std::vector<int> vec2, vec3;
int *vec4;
//First block
vec2.reserve(len);
start = clock();
vec2.assign(vec1a.begin(), vec1a.end());
stop = clock();
wr += ((double)(stop-start))/((double)(CLOCKS_PER_SEC));
//Second block
start = clock();
vec3.assign(vec1a.begin(), vec1a.end());
stop = clock();
wor += ((double)(stop-start))/((double)(CLOCKS_PER_SEC));
//Third block
vec2.clear();
start = clock();
vec2.assign(vec1b.begin(), vec1b.end());
stop = clock();
wc += ((double)(stop-start))/((double)(CLOCKS_PER_SEC));
//Fourth block
start = clock();
vec4 = new int[len];
for(int j=0; j<len; j++) vec4[j] = vec1a[j];
stop = clock();
pb += ((double)(stop-start))/((double)(CLOCKS_PER_SEC));
delete []vec4;
}
printf("With reserve() = %10.4lE\n", wr);
printf("Without reserve() = %10.4lE\n", wor);
printf("With clear() = %10.4lE\n", wc);
printf("newed int array = %10.4lE\n", pb);
return 0;
}
答案 0 :(得分:4)
考虑到矢量的源都在头文件中,您可以搜索.assign的内容。在内部分配中,它一次分配所需数量的项目。模板非常智能,当您执行vec2.assign(vec1a.begin(), vec1a.end())
如果你真的想测试它,请迭代每个项目并使用push_back而不是assign()
加成
只是为了澄清,在调用堆栈中.assign()它计算新容量并调用_Grow_to(MSVC ++ 10)。实际上,.assign()会做一个保留。
答案 1 :(得分:2)
这并不能解释您的结果,但您可能有兴趣知道reserve
和new[]
实际上都没有分配内存。相反,它们只是在您的进程中分配地址空间,只有当它们被使用时才会有虚拟内存管理器提交的实际RAM页面(并且页面将一次提交一个,部分块可能是承诺,而不是部分)。