Должен ли список объектов храниться в куче или стеке? - PullRequest
3 голосов
/ 15 марта 2009

У меня есть объект (A), у которого есть список, состоящий из объектов (B). Объекты в списке (B) являются указателями, но должен ли сам список быть указателем? Я перехожу с Java на C ++ и до сих пор не полностью привык к стеку / куче. Список не будет передан за пределы класса A, только элементы в списке. Является ли хорошей практикой выделять сам список в кучу на всякий случай?

Кроме того, должен ли класс, содержащий список (A), также находиться в самой куче? Как и список, он не будет передан.

Ответы [ 5 ]

6 голосов
/ 15 марта 2009

Имейте в виду, что

  1. Список был бы только в стеке, если бы Object-A также был в стеке
  2. Даже если сам список не находится в куче, он может выделить свое хранилище из кучи. Вот как работают std :: list, std :: vector и большинство списков C ++ - причина в том, что стековые элементы не могут расти.
  3. В наши дни большинство стеков составляют около 1 Мб, поэтому вам понадобится довольно большой список довольно больших объектов, прежде чем беспокоиться об этом. Даже если ваш стек составляет всего около 32 КБ, вы можете хранить около восьми тысяч указателей, прежде чем это станет проблемой.

ИМО люди, плохо знакомые с явным управлением памятью в C / C ++, могут иметь тенденцию переосмысливать эти вещи.

Если вы не пишете что-то, что, как вы знаете, будет иметь тысячи значительных объектов, просто поместите список в стек. Если вы не используете гигантские массивы в стиле C в функции, скорее всего, память, используемая списком, все равно окажется в куче из-за # 1 и # 2 выше.

1 голос
/ 15 марта 2009

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

Если вы абсолютно точно знаете верхнюю границу списка и она невелика по сравнению с размером вашего стека, вы, вероятно, можете сойти со стека, выделяющего список.

0 голосов
/ 15 марта 2009

Что вы подразумеваете под «списком». Если это std :: list (или std :: vector или любой другой контейнер STL), тогда он не будет хранить что-либо в стеке, так что не волнуйтесь.

Если вы сомневаетесь, посмотрите на sizeof (A), и он подскажет вам, сколько памяти он будет использовать, когда находится в стеке.

Но ... решение должно в основном основываться на времени жизни объекта. Основанные на стеке объекты уничтожаются, как только они выходят из области видимости.

0 голосов
/ 15 марта 2009

Я работаю в средах, где стек может быть небольшим и нужно избегать фрагментации кучи, поэтому я бы использовал следующие правила:

  • Если список небольшой и известен фиксированный размер, стек.

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

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

В большинстве ситуаций людям не нужно беспокоиться о фрагментации, в этом случае они, вероятно, не рекомендуют использовать alloca.

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

0 голосов
/ 15 марта 2009

Стек всегда самый простой. К сожалению, у него есть один большой недостаток - вы должны знать количество элементов заранее.

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