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

В 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;.

Есть ли столь немногие способная к перераспределению реализация средства выделения, которую это не было бы стоящий того для беспокойства? Или есть ли некоторые проблемы, которые я пропустил?

33
задан doublep 23 June 2010 в 19:49
поделиться

5 ответов

Откуда: http://www.sgi.com/tech/stl/alloc.html

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

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

19
ответ дан 27 November 2019 в 18:31
поделиться

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

8
ответ дан 27 November 2019 в 18:31
поделиться

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

Должен был быть realloc для выделения массива:

p = renew(p) [128];

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

2
ответ дан 27 November 2019 в 18:31
поделиться

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

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

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

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

13
ответ дан 27 November 2019 в 18:31
поделиться

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

3
ответ дан 27 November 2019 в 18:31
поделиться
Другие вопросы по тегам:

Похожие вопросы: