2009-11-13 60 views
3

我正在閱讀「Thinking in C++」,我對這位新操作員感到困惑。下面是書中的代碼:爲什麼新的[]分配額外的內存?

//: C13:ArrayOperatorNew.cpp 
// Operator new for arrays 

#include <new> // Size_t definition 
#include <fstream> 

using namespace std; 

ofstream trace("ArrayOperatorNew.out"); 

class Widget 
{ 
    enum { sz = 10 }; 
    int i[sz]; 

    public: 

    Widget() { trace << "*"; } 
    ~Widget() { trace << "~"; } 

    void* operator new(size_t sz) 
    { 
     trace << "Widget::new: " 
       << sz << " bytes" << endl; 
     return ::new char[sz]; 
    } 

    void operator delete(void* p) 
    { 
     trace << "Widget::delete" << endl; 
     ::delete []p; 
    } 

    void* operator new[](size_t sz) 
    { 
     trace << "Widget::new[]: " 
       << sz << " bytes" << endl; 
     return ::new char[sz]; 
    } 

    void operator delete[](void* p) 
    { 
     trace << "Widget::delete[]" << endl; 
     ::delete []p; 
    } 
}; 

int main() 
{ 
    trace << "new Widget" << endl; 
    Widget* w = new Widget; 
    trace << "\ndelete Widget" << endl; 
    delete w; 
    trace << "\nnew Widget[25]" << endl; 
    Widget* wa = new Widget[25]; 
    trace << "\ndelete []Widget" << endl; 
    delete []wa; 
} ///:~ 

,這裏是在「ArrayOperatorNew.out」

new Widget 
Widget::new: 40 bytes 
* 
delete Widget 
~Widget::delete 
new Widget[25] 
Widget::new[]: 1004 bytes 
************************* 
delete []Widget 
~~~~~~~~~~~~~~~~~~~~~~~~~ 
Widget::delete[] 

跟蹤的我感到困惑,爲什麼它不是1000號1004的內容?書中說:

這額外的四個字節就是 系統保存有 陣列的信息,特別是在陣列中 對象的數量。

但是什麼是系統?這是如何完成的?編譯器在這裏幫助?

回答

5

當使用新的[]運行時需要一些方法來記住分配的數組的大小,因此它知道多少使用delete []時要解除。在你的特定實現中,記住的方式是分配額外的四個字節來保存這個大小(它不必這樣工作)。

您可以在C++ FAQ中閱讀更多關於此的內容。

1

這是一個依賴於編譯器的細節。

當delete []被調用時,它只傳遞一個參數 - 指向數組的指針。爲了正確運行,必須知道在正確數量的對象上執行析構函數的元素數量。所以它必須在某個地方獲得這些信息。

典型的方法是new []預先加載一個額外的size_t來存儲元素數量。這樣的分配空間量會

sizeof(size_t) + numberOfElements * sizeof (ObjectType) 
0

當爲new分配一個數組時,在分配塊的開頭使用一個額外的字來保留分配的字節數。
由於C++數組不保存有關其大小的信息,因此當使用delete []時,內存管理器必須將tab分配給分配內存的大小,讀取已分配的數量,然後內存管理器收取內存量。 這就是爲什麼對單個變量調用delete []會造成災難性的原因 並且對數組調用delete會導致內存泄漏。

0

內存管理必須保留一些關於內存塊大小的信息。如果沒有這些信息,delete/delete []不能正常工作(在刪除的情況下,這個信息可能不是必須的,sinc編譯器知道被刪除的對象的大小)。

信息如何保存,以及新/刪除的實現細節在哪裏。它可能會根據編譯器或您使用的內存管理庫(例如SmartHeap)而變化。

有時會分配額外的內存來檢測編程錯誤(如在分配的內存邊界上寫入)。

相關問題