Можно ли частично удалить память из середины какого-либо объекта и «разделить» ее? - PullRequest
1 голос
/ 29 ноября 2011

Например, у меня есть массив из 200 целых чисел. Что я хочу сделать, это преобразовать его в два массива по 80 целых чисел, удалив между ними 40 целых чисел. Цель, конечно, состоит в том, чтобы использовать существующий блок памяти без выделения двух новых массивов целых чисел длиной 80 и копирования из первого массива. Я хочу сократить исходный массив с 80 до 120 и обработать то, что осталось, как два отдельных массива.

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

Например, присвоение указателей необработанным адресам памяти, где находятся срезы, и начинаются новые элементы, заставляя их действовать как массивы, использующие те же данные, уже выделенные и заполненные исходным массивом?

Естественно, я мог бы также удалить исходный массив и получить его адрес и использовать его для назначения своей области памяти новому элементу, но можно сказать C ++, по какому точному адресу выделять новый объект ? А также, существует ли способ гарантировать, что данные исходного массива не будут повреждены между его удалением и перераспределением той же области памяти в новый объект ?

Такой подход отсутствует ни в одной из прочитанных мною книг по c ++, но я чувствую, что вполне может быть какая-то низкоуровневая хитрость для достижения желаемого результата.

Ответы [ 4 ]

2 голосов
/ 29 ноября 2011

Я бы просто передал указатели на соответствующие фрагменты:

void i_need_80(int arr[80]);  // same as "int*"

std::array<int, 200> the_array;

i_need_80(the_array);
i_need_80(the_array + 120);

Вместо std::array<int, 200> вы также можете иметь динамический std::vector<int> v, в этом случае вы скажете v.data() и v.data() + 120.

Не используйте new.

2 голосов
/ 29 ноября 2011

Вы можете использовать размещение нового , но, как правило, не стоит переходить на этот низкоуровневый уровень, если вы действительно не ограничены.

Использовать это хорошая идея, когда:

  • Вы реализуете пул памяти
  • Вам необходимо выполнить запись в точное место в памяти, потому что платформа требует этого (например, отображение ввода-вывода в памяти на каком-либо встроенном устройстве).

Недостатки использования:

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

существует ли способ гарантировать, что данные исходного массива не будут повреждены между его удалением и перераспределением той же области памяти новому объекту

Нет, это зависит от ОС. Это может быть возможно с API для конкретной платформы, если он существует.

2 голосов
/ 29 ноября 2011

Да, это возможно, используя place-new . Однако нет способа гарантировать, что содержимое ячейки памяти не будет изменено между удалением и перераспределением. В любом случае, размещение нового позволяет вам только создать объект в памяти , который у вас уже есть . Поэтому вам нужно выделить пул памяти, а затем выполнить собственное управление памятью в этом пуле.

0 голосов
/ 29 ноября 2011

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...