Лучше ли использовать вектор, содержащий указатели, или вектор значений (чтобы избежать фрагментации кучи)?

Мне известно о многих статьях по предотвращению фрагментации кучи. Мой вопрос касается конкретно того, что происходит, когда мы используем вектор для хранения данных:

class foo{
public:
std::vector<bar>; // Or I can have std::vector<bar*>
};

У меня нет проблем с использованием new или delete (у меня нет утечек памяти, и мне очень ясно, когда панель не используется, и я могу вызвать delete при необходимости). Но что касается фрагментации кучи, что лучше? Это делает переполнение стека более вероятным?

РЕДАКТИРОВАТЬ: У меня нет никакой новой информации, чтобы добавить. Я просто хотел поблагодарить всех и сказать, что я обнаружил, что любой вопрос, помеченный C ++, похоже, привлекает так много знающих и полезных людей. Это действительно довольно мило. Спасибо.

1

Решение

std::vector гарантирует, что его содержимое будет храниться в постоянной памяти. Если вы храните объекты в своем векторе, то каждый объект будет находиться рядом друг с другом в большом куске памяти, но если вы поместите указатели на вектор, которые указывают на объекты, созданные с помощью newТогда каждый объект будет в случайных местах в памяти.

Поэтому первая версия (хранение объектов, а не указателей) лучше как для избежания фрагментации кучи, так и для использования кеша.

1

Другие решения

TL; DR, если у вас нет веских причин, с измерениями звука, всегда предпочитайте использовать vector с типами значений.

Я бы поспорил за std::vector<bar> форма. Если у вас нет других (взвешенных) причин, почему гарантированная непрерывная память vector с типом значения это лучшая идея. Когда вектор выделяет непрерывный блок памяти, объекты будут размещаться в памяти рядом друг с другом (с некоторым запасом). Это позволяет хост-системе и среде выполнения лучше избегать фрагментации. Выделение объектов по отдельности может привести к фрагментации, поскольку вы не контролируете, где они расположены.

Я отмечаю ваши опасения по поводу стека; vector имеет небольшое выделение стека, так что это не должно быть проблемой, «обычный» распределитель std::allocator использования new выделить память для vector в кучу.

Зачем vector всегда быть любимым? Херб Саттер подробно рассказывает об этом; http://channel9.msdn.com/Events/Build/2014/2-661 с поддерживающими графиками, диаграммами, объяснениями и т. д. около отметки 23:30, и он берет материал Бьярне около отметки 46:00.

2

У ОП, похоже, есть принципиальное недопонимание того, что std::vector делает: выделяет непрерывный блок памяти в кучу, вам не нужно беспокоиться о вашем стековом пространстве при использовании vector! Поэтому, когда вам действительно не нужно ничего хранить, кроме самих объектов, просто положите их в свой vector и ты хороший.

Так std::vector<bar> кажется правильным выбором в вашем случае. Кроме того, не беспокойтесь о фрагментации кучи преждевременно, пусть об этом беспокоится компилятор. (Но вы должны беспокоиться о кормлении предварительного сборщика, вот почему std::vector<bar> должен быть вашим стандартным выбором для хранения что-нибудь.)

1

Используйте вектор указателей в следующих случаях:

  • Bar — это базовый класс, и вы хотите хранить экземпляры производных классов в векторе.
  • Бар не имеет соответствующего конструктора копирования / перемещения или запретительно дорого.
  • Вы хотите хранить указатели на объекты в векторе в другом месте, и вы можете изменить емкость вектора (например, из-за изменения размера или push_back). Если объекты хранятся по значению, старые указатели станут недействительными при изменении емкости.
  • Вы хотите, чтобы некоторые элементы в векторе были «пустыми» (которые могут быть представлены нулевыми указателями), и вместо этого нецелесообразно хранить фиктивные, неиспользуемые экземпляры Bar в векторе по значению.

Если вам нужны указатели, я настоятельно рекомендую использовать умные указатели.

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

1
По вопросам рекламы [email protected]