Почему в распределителях C ++ отсутствует функция перераспределения?

StackOverflow https://stackoverflow.com/questions/3105001

  •  29-09-2019
  •  | 
  •  

Вопрос

В 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

Это, наверное, самое сомнительное дизайнерское решение. Вероятно, было бы немного полезнее предоставить версию reallocate, которая либо изменяла размер существующего объекта без копирования, либо возвращала значение NULL.Это сделало бы его непосредственно полезным для объектов с конструкторами copy .Это также позволило бы избежать ненужного копирования в случаях, в которых исходный объект не был полностью заполнен.

К сожалению, это привело бы к запрету использования realloc из библиотеки C .Это, в свою очередь, добавило бы сложности многим реализациям распределителя и усложнило бы взаимодействие с инструментами отладки памяти .Таким образом, мы решили отказаться от этой альтернативы.

Другие советы

На самом деле это недостаток дизайна, на который указывает Александреску со стандартными распределителями (не operator new []/ delete [], а то, что изначально было распределителями stl, используемыми для реализации std:: vector, например).

Перераспределение может произойти значительно быстрее, чем malloc, memcpy и free.Однако, хотя размер фактического блока памяти может быть изменен, он также может переместить память в новое место.В последнем случае, если блок памяти состоит из не-модулей, все объекты необходимо будет уничтожить и создать копию после перераспределения.

Главное, что стандартная библиотека должна вместить это как возможность является функцией перераспределения как часть общедоступного интерфейса стандартного распределителя.Такой класс, как std::vector, безусловно, мог бы использовать его, даже если реализация по умолчанию заключается в malloc нового размера блока и освобождении старого.Это должна быть функция, способная уничтожать и копировать-создавать объекты в памяти, хотя, если она это сделает, она не сможет обрабатывать память непрозрачным образом.Здесь есть небольшая сложность, и потребуется еще немного поработать с шаблоном, возможно, именно поэтому он был исключен из стандартной библиотеки.

std:: вектор<...>:: резерв недостаточен:это касается другого случая, когда размер контейнера можно предвидеть.Для списков действительно переменного размера решение перераспределения могло бы сделать смежные контейнеры, такие как std ::vector, намного быстрее, особенно если оно может иметь дело со случаями перераспределения, когда размер блока памяти был успешно изменен без перемещения, и в этом случае оно может опустить вызов конструкторов копирования и деструкторов для объектов в памяти.

То, о чем вы просите, по сути, это то, что vector::reserve делает.Без семантики перемещения объектов невозможно перераспределить память и перемещать объекты без выполнения копирования и уничтожения.

Из-за объектно-ориентированной природы C ++ и включения различных стандартных типов контейнеров, я думаю, что просто меньше внимания уделялось управлению оперативной памятью, чем в C.Я согласен, что в некоторых случаях функция realloc() была бы полезна, но необходимость исправить это минимальна, поскольку почти всю результирующую функциональность можно получить, используя вместо этого контейнеры.

Я думаю, это одна из тех вещей, когда бог пошел не так, но мне просто было слишком лениво писать в комитет по стандартам.

Должно было произойти перераспределение для распределения массива:

p = renew(p) [128];

или что-то в этом роде.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top