2013-01-17 27 views
0

我一直在使用gprof在一個簡單版本的向量上分配堆上的內存(沒有實際上是動態的 - 僅用於測試目的)運行測試。事情是,看看我看到'new []'和'delete []'之間的巨大差異 - 因爲我實際上向vector中插入了值(使用[]運算符)。 做上述,我得到了類似的結果:刪除[]工作比新的[]慢嗎?

% 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; 
} 
+8

你能顯示一些代碼嗎? – Default

+3

'[]'不會插入或分配任何.... – Pubby

+6

如果'調用1'意味着您在測試過程中只會調用一次這些函數,那麼我會質疑這些數字的價值。至少叫他們幾千次。 – Mat

回答

1

你是對的。 new[]並不真正在所有系統上分配內存。例如,在Linux上,你會得到一個指向內存的指針,只有在嘗試實際使用它時纔會分配內存。所以:

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

其中something是一個指向一個內置類型,幾乎是無操作。 (這可能會破壞標準的一致性,因爲new應該在沒有更多內存可用時拋出(或者在不支持的版本中返回NULL)。但事實就是這樣; Linux幾乎把它看作是無限的內存)。

請注意,這僅適用於內置類型,因爲它們沒有使用new[]進行默認構建,除非您提出要求。其他類型的默認ctor被調用,因此內存被訪問。爲了測試,請嘗試訪問最後一個元素:

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

這是否會改變您的gprof結果?如果是,那麼延遲分配很可能是你所看到的原因。

+0

正確但無意義。 'new []'不分配真實內存,但絕對不會分配地址空間。而昂貴的部分是找到一個_contiguous_塊的地址空間。由於MMU的原因,實際內存不會被連續映射。 – MSalters

+0

@MSalters是否確定地址空間分配在使用之前不會延遲?你最初得到的指針可以映射到任何地方。 –

+0

除非最新的標準改變了事情(我最近在C++中沒有太多工作),需要調用基於數組的'new'運算符來調用數組中每個元素的默認構造函數。這要求它不僅找到(或構造)連續的地址空間,還要引用新的對象來構建它們。這聽起來很像我的_allocation_。 –