C++ 3d.Комментарии

       

Выделение памяти под массив


На этом пункте стоит остановиться поподробнее, так как с оператором new[] связаны не вполне очевидные вещи. Не мудрствуя лукаво, привожу перевод раздела 10.3 "Array Allocation" из книги "The Design and Evolution of C++" одного известного автора:

Определенный для класса X оператор X::operator new() используется исключительно для размещения одиночных объектов класса X (включая объекты производных от X классов, не имеющих собственного распределителя памяти). Следовательно X* p = new X[10];

не вызывает X::operator new(), т.к. X[10] является массивом, а не объектом класса X.

Это вызывало много жалоб, т.к. я не разрешил пользователям контролировать размещение массивов типа X. Однако я был непреклонен, т.к. массив элементов типа X -- это не объект типа X, и, следовательно, распределитель памяти для X не может быть использован. Если бы он использовался и для распределения массивов, то автор X::operator new() должен был бы иметь дело как с распределением памяти под объект, так и под массив, что сильно усложнило бы более распространенный случай. А если распределение памяти под массив не очень критично, то стоит ли вообще о нем беспокоиться? Тем более, что возможность управления размещением одномерных массивов, таких как X[d] не является достаточной: что, если мы захотим разместить массив X[d][d2]?

Однако, отсутствие механизма, позволяющего контролировать размещение массивов вызывало определенные сложности в реальных программах, и, в конце концов, комитет по стандартизации предложил решение данной проблемы. Наиболее критичным было то, что не было возможности запретить пользователям размещать массивы в свободной памяти, и даже способа контролировать подобное размещение. В системах, основанных на логически разных схемах управления размещением объектов это вызывало серьезные проблемы, т.к. пользователи наивно размещали большие динамические массивы в обычной памяти. Я недооценил значение данного факта.

Принятое решение заключается в простом предоставлении пары функций, специально для размещения/освобождения массивов: class X { // ... void* operator new(size_t sz); // распределение объектов void operator delete(void* p);

void* operator new[](size_t sz); // распределение массивов void operator delete[](void* p); };

Распределитель памяти для массивов используется для массивов любой размерности. Как и в случае других распределителей, работа operator new[] состоит в предоставлении запрошенного количества байт; ему не нужно самому беспокоиться о размере используемой памяти. В частности, он не должен знать о размерности массива или количестве его элементов. Laura Yaker из Mentor Graphics была первой, кто предложил операторы для размещения и освобождения массивов.



Содержание раздела