vector :: reserve()似乎没有分配空间

时间:2011-01-24 18:58:58

标签: performance stl

附加代码包含对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;
}

2 个答案:

答案 0 :(得分:4)

考虑到矢量的源都在头文件中,您可以搜索.assign的内容。在内部分配中,它一次分配所需数量的项目。模板非常智能,当您执行vec2.assign(vec1a.begin(), vec1a.end())

时,它知道它需要1E8

如果你真的想测试它,请迭代每个项目并使用push_back而不是assign()

加成

只是为了澄清,在调用堆栈中.assign()它计算新容量并调用_Grow_to(MSVC ++ 10)。实际上,.assign()会做一个保留。

答案 1 :(得分:2)

这并不能解释您的结果,但您可能有兴趣知道reservenew[]实际上都没有分配内存。相反,它们只是在您的进程中分配地址空间,只有当它们被使用时才会有虚拟内存管理器提交的实际RAM页面(并且页面将一次提交一个,部分块可能是承诺,而不是部分)。