С++ Когда выделять в куче или стеке?

Задавая другой вопрос (а также раньше), мне было интересно, как мне решить, создавать ли объект в куче или сохранять его как объект в стеке? Что я должен спросить себя об объекте, чтобы сделать правильное распределение?


person user997112    schedule 20.09.2013    source источник


Ответы (5)


Поместите его в кучу, если нужно, и в стек, если можете.

Какие вещи нужно положить в кучу? Что угодно разной длины. Любой объект, который может быть нулевым. Все, что очень большое, чтобы не вызвать переполнение стека.

person Steve Howard    schedule 20.09.2013
comment
Я согласен с вашим утверждением, за исключением того, что я не понимаю Любой объект, который может иметь значение null . Что вы подразумеваете под нулем? Конечно, не традиционные NULL или nullptr. - person Mark Lakata; 14.09.2015

Простой ответ.

Когда он выходит за рамки, хотите ли вы, чтобы он зависал и мог его использовать?

person Ed Heal    schedule 20.09.2013
comment
Следует отметить, что помещать в стек гигантские объекты также не рекомендуется, даже если они удовлетворяют другим критериям. Особенно не весело в С++, чтобы выйти за пределы вашего стека. - person Voo; 21.09.2013
comment
@Voo Да, но как часто это происходит? Классы-контейнеры динамически выделяют свою память, поэтому я думаю, что можно с уверенностью сказать, что объект размером 1 КБ (а) огромный и (б) редкий. Давайте рассмотрим стек вызовов глубиной 50 с 20 такими огромными объектами в кадре стека каждой функции, и вы по-прежнему имеете только 1 МБ стека. - person us2012; 21.09.2013
comment
@voo - Вы можете увеличить размер стека. Вы также можете писать код без кучи, как это требуется в различных отраслях, критически важных с точки зрения безопасности. - person Ed Heal; 21.09.2013
comment
И вам не кажется, что вам нужно изменить конкретное ограничение ОС для выполнения вашего кода, особенно плохой дизайн? Особенно проблематично, если лимит зависит от размера ввода. @us2012 Редкая ситуация? Я бы очень на это надеялся, но какое это имеет отношение к советам о том, что делать, если вы находитесь именно в одном из этих случаев? - person Voo; 21.09.2013
comment
@voo - Если программное обеспечение имеет фиксированные входы (например, электростанция) и программное обеспечение должно работать круглосуточно и без выходных, избегая фрагментации памяти и проблем, связанных с оборванными указателями, то нет. Добро пожаловать в мир критически важного для безопасности программного обеспечения# - person Ed Heal; 21.09.2013
comment
@Ed Итак, ваш ответ основан на какой-то чрезвычайно редкой ситуации, с которой большинство людей не столкнется, и вы не понимаете, почему упоминание повседневных проблем, с которыми могут столкнуться все остальные, было бы важно? Вам не нужно беспокоиться об освобождении памяти. Это также верный совет в некоторых ситуациях, но это не значит, что вы должны просто позиционировать его как общий совет. - person Voo; 21.09.2013
comment
@voo - Если вы можете избежать кучи (т. Е. Использовать стек), об этом стоит подумать. Экономит много хлопот. - person Ed Heal; 21.09.2013
comment
@Ed И все дело в том, когда можно избежать кучи, а когда нет. Не упоминание сценария, в котором использование стека во многих ситуациях закончится плохо, потому что он отлично работает в какой-то конкретной подкатегории, не поможет. - person Voo; 21.09.2013
comment
@voo - Просто указываю на тот факт, что вы можете полностью избежать кучи. Поэтому стоит упомянуть, что человек может пожелать, чтобы рассматриваемое программное обеспечение было очень надежным. - person Ed Heal; 21.09.2013

Зависит от предполагаемого срока службы объекта.

  • Если вы хотите, чтобы объект оставался живым даже после возврата функции, тогда HEAP, иначе STACK

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

person Arun    schedule 20.09.2013
comment
Если, конечно, вы не вернете указанный объект из функции. Кроме того, во многих случаях полезно возвращать объект по значению, а не по указателю на него. - person us2012; 21.09.2013
comment
Необходимо учитывать статические данные - person Ed Heal; 21.09.2013

Две причины использовать кучу:

1- Вам нужны данные после текущей области.

2- Вы хотите зарезервировать большой объем памяти.

В остальном оставайтесь в стеке.

Примечание: не резервируйте много памяти в стеке, иначе вы получите «переполнение стека»;)

person The Quantum Physicist    schedule 20.09.2013

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

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

Для долгоживущих данных и для больших данных (несколько КБ и более) вы должны использовать кучу.

Опасность выделения большего стека заключается в том, что это может повредить вам, если вы запускаете несколько потоков. Вы должны определить размер стека для использования в «худшем случае». Каждому потоку требуется свой собственный стек. На машине с большим количеством ядер (где у вас может быть запущено более 200 потоков) вы можете не захотеть произвольно увеличивать стек. С другой стороны, куча не должна быть рассчитана на использование в "худшем случае" - это намного эффективнее.

person Mark Lakata    schedule 14.09.2015