В C стандартные функции обработки памяти malloc()
, realloc()
и free()
. Однако C++ stdlib средства выделения только параллелен двум из них: нет никакой функции перераспределения. Конечно, не было бы возможно сделать точно то же как realloc()
, потому что просто копирование памяти не подходит для несоставных типов. Но там была бы проблема с, скажем, этой функцией:
bool reallocate (pointer ptr, size_type num_now, size_type num_requested);
где
ptr
ранее выделяется с тем же средством выделения для num_now
объекты;num_requested
>= num_now
;и семантика следующим образом:
ptr
от размера для num_now
объекты к num_requested
объекты, это делает так (оставляющий дополнительную неинициализированную память) и возвраты true
;false
.Предоставленный, это не очень просто, но средства выделения, как я понимаю, главным образом предназначены для контейнеров, и код контейнеров уже является обычно сложным.
Учитывая такую функцию, std::vector
, Скажем, мог вырасти, следующим образом (псевдокодируйте):
if (allocator.reallocate (buffer, capacity, new_capacity))
capacity = new_capacity; // That's all we need to do
else
... // Do the standard reallocation by using a different buffer,
// copying data and freeing the current one
Средства выделения, которые неспособны к изменению емкости памяти в целом, могли просто реализовать такую функцию безусловным return false;
.
Есть ли столь немногие способная к перераспределению реализация средства выделения, которую это не было бы стоящий того для беспокойства? Или есть ли некоторые проблемы, которые я пропустил?
Откуда: http://www.sgi.com/tech/stl/alloc.html
Это, наверное, самый сомнительный дизайнерское решение. Было бы наверное, было немного полезнее предоставить версию перераспределения, которая либо изменил размер существующий объект без копирования или вернул NULL. Это сделало бы это непосредственно полезно для объектов с копией конструкторы. Также было бы избежать ненужного копирования в случаях в котором исходный объект не были полностью заполнены.
К сожалению, это было бы запрещено использование realloc из C библиотека. Это, в свою очередь, добавило бы сложность для многих распределителей реализации, и сделал бы взаимодействие с отладкой памяти инструменты посложнее. Таким образом мы решили против этой альтернативы.
То, что вы просите, по сути является тем, что делает vector :: reserve
. Без семантики перемещения для объектов невозможно перераспределить память и перемещать объекты без копирования и уничтожения.
Думаю, это одна из тех вещей, где бог ошибся, но мне было просто лень писать в комитет по стандартам.
Должен был быть realloc для выделения массива:
p = renew(p) [128];
или что-то вроде этого.
На самом деле это недостаток дизайна, который Александреску указывает на стандартные распределители (не оператор new [] / delete [], а то, что изначально было распределителями stl, используемыми, например, для реализации std :: vector).
Перераспределение может происходить значительно быстрее, чем malloc, memcpy и free. Однако, хотя размер фактического блока памяти можно изменять, он также может перемещать память в новое место. В последнем случае, если блок памяти состоит из не-POD, все объекты должны быть уничтожены и скопированы после перераспределения.
Главное, что необходимо стандартной библиотеке, чтобы учесть это как возможность , - это функция перераспределения как часть открытого интерфейса стандартного распределителя. Такой класс, как std :: vector, безусловно, мог бы использовать его, даже если реализация по умолчанию состоит в том, чтобы выделить новый размер блока и освободить старый. Это должна быть функция, способная разрушать и копировать объекты в памяти, хотя она не сможет обрабатывать память непрозрачным образом, если она это сделает. Здесь есть небольшая сложность и потребуется дополнительная работа с шаблоном, что может быть причиной того, что она не была включена в стандартную библиотеку.
std :: vector <...> :: reserve недостаточно: он обращается к другому случаю, когда размер контейнера можно предвидеть.Для списков действительно переменного размера решение с перераспределением может сделать смежные контейнеры, такие как std :: vector, намного быстрее, особенно если оно может иметь дело со случаями перераспределения, когда размер блока памяти был успешно изменен без перемещения, и в этом случае он может опустить вызов копирования конструкторы и деструкторы для объектов в памяти.
Из-за объектно-ориентированной природы C++ и включения различных стандартных типов контейнеров, я думаю, что просто меньше внимания было уделено управлению памятью направления, чем в C. Я согласен, что есть случаи, когда realloc() был бы полезен, но давление для исправления этого минимально, так как почти вся результирующая функциональность может быть получена при использовании контейнеров вместо этого.