2009-11-13 7 views
3

Я читаю «Думая на 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[] 

Я запутался о количестве 1004. Почему это не 1000? В книге говорится:

Эти дополнительные четыре байта, где система хранит информацию о массиве, в частности, число объектов в массиве.

Но какая система? Как это достигается? Компилятор помогает здесь?

ответ

5

При использовании нового [] исполняющую необходим способ запомнить размер массива выделенных, поэтому он знает, сколько для освобождения при использовании удаления []. В вашей конкретной реализации это способ запоминания - выделить дополнительные четыре байта, которые содержат размер (ему не нужно работать таким образом).

Подробнее об этом можно узнать в C++ FAQ.

1

Это детали, зависящие от компилятора.

При вызове delete [] передается только один параметр - указатель на массив. Чтобы правильно работать, он должен знать количество элементов для выполнения деструкторов на точно правильном количестве объектов. Поэтому он должен получить эту информацию где-нибудь.

Типичный подход заключается в том, что новый [] добавляет полезную нагрузку массива с дополнительным size_t, который хранит количество элементов. Таким образом, объем пространства, выделенного будет

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

При назначении массива с новым затем в начале выделенного блока используется дополнительное слово, чтобы сохранить количество выделенных байтов.
Поскольку массив C++ не хранит информацию об их размере, диспетчер памяти должен хранить вкладки по размеру выделенной памяти, при использовании delete [] количество выделенных байтов считывается, а затем менеджер памяти платит этот объем памяти , Именно поэтому вызов delete [] для одной переменной может быть катастрофическим и вызов delete для массива вызывает утечку памяти.

2

Этот FAQ After p = new Fred[n], how does the compiler know there are n objects to be destructed during delete[] p? отвечает именно на этот вопрос.

+0

хорошо ... Я хочу знать, как вы просматриваете ссылку на часто задаваемые вопросы, когда у меня возникает вопрос? Кажется, мне нужно сначала повысить свою способность к поиску. :) – iBacchus

0

Управление памятью должно содержать некоторую информацию о размере блока памяти. Без этой информации удаление/удаление [] не могут работать корректно (в случае удаления эта информация может не понадобиться, компилятор знает размер удаляемого объекта).

Как хранится информация и где представлена ​​деталь реализации нового/удалить. Он может изменяться в зависимости от используемого вами компилятора или библиотеки управления памятью (например, SmartHeap).

Иногда для обнаружения ошибок программирования выделяется дополнительная память (например, запись по границе выделенной памяти).

Смежные вопросы