Напротив, вы всегда должны отдавать предпочтение распределению стека, поскольку, как показывает практическое правило, вы никогда не должны иметь new / delete в вашем пользовательском коде.
Как вы говорите, когда переменная объявляется в стеке, ее деструктор автоматически вызывается, когда она выходит за пределы области видимости, что является вашим основным инструментом для отслеживания времени жизни ресурса и предотвращения утечек.
Итак, в общем, каждый раз, когда вам нужно выделить ресурс, будь то память (путем вызова new), дескрипторы файлов, сокеты или что-то еще, оберните его в класс, в котором конструктор получает ресурс, а деструктор освобождает его. Затем вы можете создать объект этого типа в стеке, и вам будет гарантировано, что ваш ресурс будет освобожден, когда он выйдет за пределы области видимости. Таким образом, вам не нужно везде отслеживать ваши новые / удаляемые пары, чтобы избежать утечек памяти.
Наиболее распространенное название этой идиомы - RAII.
Также изучите классы интеллектуальных указателей, которые используются для обертывания результирующих указателей в редких случаях, когда вам действительно нужно выделить что-то с новым за пределами выделенного объекта RAII. Вместо этого вы передаете указатель на интеллектуальный указатель, который затем отслеживает его время жизни, например, путем подсчета ссылок, и вызывает деструктор, когда последняя ссылка выходит за пределы области видимости. Стандартная библиотека предназначена std::unique_ptr
для простого управления на основе области действия и std::shared_ptr
подсчета ссылок для реализации совместного владения.
Многие учебные пособия демонстрируют создание экземпляров объекта с помощью таких фрагментов, как ...
Итак, вы обнаружили, что большинство руководств - отстой. ;) Большинство руководств преподают вам паршивые методы работы с C ++, включая вызов new / delete для создания переменных, когда в этом нет необходимости, и затрудняющие отслеживание времени жизни ваших выделений.
Хотя наличие вещей в стеке может быть преимуществом с точки зрения распределения и автоматического освобождения, у него есть некоторые недостатки.
Возможно, вы не захотите размещать огромные объекты в стеке.
Динамическая рассылка! Рассмотрим этот код:
Это напечатает "B". Теперь посмотрим, что происходит при использовании Stack:
Будет выведено «A», что может быть не интуитивно понятно тем, кто знаком с Java или другими объектно-ориентированными языками. Причина в том, что у вас больше нет указателя на экземпляр
B
. Вместо этого создается экземпляр,B
который копируется вa
переменную типаA
.Некоторые вещи могут происходить неожиданно, особенно если вы новичок в C ++. В C у вас есть указатели, и все. Вы знаете, как их использовать, и они ВСЕГДА делают то же самое. В C ++ это не так. Только представьте, что происходит, когда вы используете в этом примере в качестве аргумента для метода - все становится сложнее, и он ДЕЙСТВИТЕЛЬНО имеет огромное значение, если
a
он типаA
илиA*
или дажеA&
(вызов по ссылке). Возможны многие комбинации, и все они ведут себя по-разному.источник
Что ж, причина для использования указателя будет точно такой же, как и причина использования указателей в C, выделенных с помощью malloc: если вы хотите, чтобы ваш объект жил дольше, чем ваша переменная!
Даже настоятельно рекомендуется НЕ использовать оператор new, если вы можете этого избежать. Особенно, если вы используете исключения. В общем, гораздо безопаснее позволить компилятору освобождать ваши объекты.
источник
Я видел этот антипаттерн от людей, которые не совсем понимают оператор & address-of. Если им нужно вызвать функцию с указателем, они всегда будут выделять память в куче, чтобы получить указатель.
источник
Относитесь к куче как к очень важному объекту недвижимости и используйте его очень разумно. Основное правило большого пальца заключается в стек использования по возможности и использовать кучу, когда нет другого пути. Располагая объекты в стеке, вы можете получить множество преимуществ, таких как:
(1). Вам не нужно беспокоиться о раскручивании стека в случае возникновения исключений.
(2). Вам не нужно беспокоиться о фрагментации памяти, вызванной выделением вашим диспетчером кучи больше места, чем необходимо.
источник
Единственная причина, по которой я бы беспокоился, это то, что Dog теперь размещается в стеке, а не в куче. Так что, если размер Dog составляет мегабайты, у вас может быть проблема,
Если вам все-таки нужно пойти по новому / удаленному маршруту, будьте осторожны с исключениями. И из-за этого вы должны использовать auto_ptr или один из типов интеллектуальных указателей boost для управления временем жизни объекта.
источник
Нет причин для нового (в куче), когда вы можете выделить в стеке (если по какой-то причине у вас есть небольшой стек и вы хотите использовать кучу.
Возможно, вы захотите рассмотреть возможность использования shared_ptr (или одного из его вариантов) из стандартной библиотеки, если вы хотите разместить в куче. Это сделает удаление за вас, как только все ссылки на shared_ptr перестанут существовать.
источник
Существует еще одна причина, о которой никто не упомянул, почему вы можете создать свой объект динамически. Динамические объекты на основе кучи позволяют использовать полиморфизм .
источник
У меня была такая же проблема в Visual Studio. Вы должны использовать:
yourClass-> classMethod ();
скорее, чем:
yourClass.classMethod ();
источник