Использование размещения нового в векторном контейнере - PullRequest
1 голос
/ 22 апреля 2011

Если у меня есть контейнер:

std::vector<T*> elements;

могу ли я использовать размещение new для размещения моих объектов так, чтобы все объекты располагались смежно? Так что я могу сделать что-то вроде этого:

size_t elementIndex = someRandomElement - elements[0];

Где someRandomeElement - это случайный элемент из elements, а elementIndex будет хранить правильный индекс someRandomElement, так что elements[elementIndex] == someRandomElement

Это необходимо для моей текущей реализации менеджера памяти. У меня есть реализация, которую я смог завершить сегодня, но она требует, чтобы элементы (которые могут быть вокселем, треугольником или чем-то еще) имели функцию GetIndex () и SetIndex (), чтобы при возврате элемента в качестве указателя Я могу узнать индекс элемента в массиве elements, что означает, что любые элементы, которые я не могу изменить (скажем, Ogre :: Vector3), не могут использовать менеджер (в моем случае они нужны мне, потому что он они фрагментируют память).

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

ПРИМЕЧАНИЕ: есть аналогичный вопрос , который я отправил сегодня, но ответы там делают некоторые предположения, которые полностью соответствуют моим требованиям. Одним из требований является то, что вектор должен быть заполнен указателями на T, в противном случае большая часть кодовой базы должна измениться. Во-вторых, инициализация более 100 000 (приблизительно) элементов приводит к исключению bad_alloc. Каждый элемент имеет размер 196 байт (мне удалось уменьшить его до 132 байт).

Ответы [ 2 ]

2 голосов
/ 22 апреля 2011

Чтобы сделать ваши указанные объекты смежными, у вас есть два разумных варианта:

  • используйте new[], чтобы создать один массив элементов, достаточно большой, чтобы вместить их все, затем присвоить им новые значения и поместить их адреса в элементы
  • используйте malloc () для создания достаточно большой неинициализированной области памяти, чтобы вместить их все (вероятно, она будет достаточно строго выровнена, но вы должны знать об этой проблеме), затем используйте размещение new, чтобы сконструировать элементы в эта память

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

Если у вас недостаточно памяти для выделения большого массива, тогда, очевидно, вы не сможете сделать это ... просто так. Можно ожидать, что для 100 000 отдельных new T s потребуется больше памяти, чем для одного new T[100000], хотя ... с выделением связаны накладные расходы на заполнение и управление кучей.

1 голос
/ 22 апреля 2011

Исключение std::bad_alloc, вероятно, связано с тем, что вы пытаетесь выделить слишком большой непрерывный блок памяти. Итак, рассмотрите использование вместо std::deque<T>.

Если вы по какой-то причине решите, что вам все еще нужен std::vector<T*>, вы можете хранить указатели на элементы в std::deque<T>. Пока вы только добавляете и удаляете элементы в начале или конце последовательности, вам не нужно беспокоиться об аннулировании указателей.

...