0

我一直在使用 gprof 在一个简单版本的向量上运行测试,该向量在堆上分配内存(实际上并不是动态的 - 仅用于测试目的)。问题是,在查看结果时,我发现 'new[]' 和 'delete[]' 之间存在巨大差异——因为我实际上将值插入到向量中(使用 [] 运算符)。执行上述操作,我得到如下结果:

%   cumulative   self              self     total           
  time   seconds   seconds    calls   s/call   s/call  name    
  0.92      0.55      0.01        1     5.03     5.03  MyVector::~MyVector()
  0.00      0.55      0.00        1     0.00     0.00  MyVector::MyVector(int)

但是如果我只是分配内存并删除它,而不实际将值插入向量,它们的工作速度同样快:

%   cumulative   self              self     total           
time   seconds   seconds    calls  ms/call  ms/call  name    
0.00      0.09     0.00        1     0.00     0.00  MyVector::MyVector(int)
0.00      0.09     0.00        1     0.00     0.00  MyVector::~MyVector()

我的猜测是,当使用'new []'时,编译器(在我的例子中是gcc)并没有真正分配内存,只有在它需要时才会这样做(比如使用[]时)。并且当它需要销毁对象时,它必须取消分配在每次访问期间分配的所有内存(使用 [])。

我找不到任何文档 - 也许有一些我不知道的东西。如果有人能分享他关于这个问题的知识,我会很高兴。

编辑:我添加了我使用的代码。感谢到目前为止的所有答案:

class MyVector
{
public:

        MyVector(int size) { _data = new int[size]; };
        ~MyVector() { delete[] _data; } ;

        int& operator[](int index) { return _data[i]; };

 private:
       int* _data;
       int _size;     
 };


    And the test:

int main() {

      MyVector v(1000000);

      for (int j = 0 ; j<20000 ; ++j) {
        for (int i = 0; i<1000000; ++i) {
          v[i]= i; //If i remove this line, destructor and constructor work just as fast
        }
     }

      return 0;
}
4

1 回答 1

1

你是对的。new[]并没有真正立即在所有系统上分配内存。例如,在 Linux 上,您会得到一个指向内存的指针,只有在您尝试实际使用它时才会分配该内存。所以:

something = new[N];
delete[] something;

wheresomething是指向内置类型的指针,几乎是无操作的。

(这可能违反标准一致性,因为new应该在没有更多可用内存时抛出(或在 nothrow 版本中返回 NULL)。但事实就是如此;Linux 几乎将其视为具有无限内存。)

请注意,这仅适用于内置类型,因为new[]除非您要求,否则它们不会使用默认构造。其他类型的默认 ctor 被调用,因此内存被访问。为了测试,尝试只访问最后一个元素:

something = new[N];
something[N-1] = some_Value;
delete[] something;

这会改变你的 gprof 结果吗?如果是,那么延迟分配很可能是您所看到的原因。

于 2013-01-17T12:02:41.690 回答