Если вы напишите свой код правильно, вам не придется об этом беспокоиться, по крайней мере, не напрямую.Вам доступны библиотечные средства, которые управляют управлением памятью и другими ресурсами полностью автоматически, так что вам это не нужно.
C ++ предоставляет нечто гораздо лучшее, чем сборщик мусора: он обеспечивает детерминированное уничтожение всех объектов, и это детерминированное уничтожение может использоваться для автоматического управления временем жизни каждого ресурса, в отличие от сборки мусора, которая (во многих распространенных реализациях)только позволяет автоматически управлять памятью и вручную управлять всеми другими ресурсами, требующими детерминированной очистки.
Если вы динамически выделяете объект, используйте умный указатель для управления его временем жизни.Если вам не нужно делиться правами собственности, вы можете использовать std::unique_ptr
, который позволяет вам передавать права собственности от одного владельца другому.Если вам нужно разделить владение, вы можете использовать std::shared_ptr
, который использует технику подсчета ссылок для поддержания общего владения.
Есть два важных правила, о которых следует помнить:
Если вам нужно написать delete
в вашей программе на C ++, код почти наверняка неправильный. C ++ обеспечивает автоматическое управление временем жизни для всех ресурсов, включая память, и вы должны воспользоваться этим,Единственное место, которое должно появиться delete
, - это код библиотеки, в котором реализованы контейнеры, владеющие ресурсами, и, возможно, более редкий низкоуровневый код.
Предпочитают работать с объектами,вместо указателей на объекты, где это возможно. Где возможно, следует избегать явного динамического выделения.C ++ не похож на такие языки, как C # и Java, где большинство объектов создаются в куче.В C ++ часто лучше создавать объекты в стеке (используя автоматические переменные) и возвращать их по значению.
Чтобы ответить на ваши конкретные сценарии:
Объект помещается в какой-то контейнер.Кто отвечает за освобождение памяти.Что, если несколько классов совместно используют один и тот же объект?
Вы должны по возможности предпочитать хранить сами объекты в контейнере, а не указатели на объекты.Если вам по какой-то причине нужно хранить указатели на объекты, вы должны использовать контейнер (например, std::vector
) интеллектуальных указателей.Если контейнер является единственным владельцем динамически размещенных объектов, вы можете использовать std::vector<std::unique_ptr<T>>
;если контейнер будет делиться правами собственности на объекты, вы можете использовать std::vector<std::shared_ptr<T>>
.
Factory pattern.Мне нравится использовать иерархию классов, где у родительского класса есть метод для создания дочерних объектов?
Это ничем не отличается от предыдущего сценария: если у вас есть дерево, довольно просто использоватьstd::vector<T>
(или std::vector<std::unique_ptr<T>>
, если вам нужны динамически распределяемые дочерние элементы) для владения дочерними элементами.
Есть ли способ предложить вызывающему методу, что возвращаемый объект находится во владении вызываемого объекта?/caller.
Если объект принадлежит исключительно вызываемому объекту (например, в std::unique_ptr
), то вы можете вернуть этот умный указатель;это передаст право владения вызывающей стороне.
Если существует общее владение объектом (например, в std::shared_ptr
), то возврат умного указателя сделает звонящего одним из владельцев;последний владелец, отказавшийся от владения (путем уничтожения или иного сброса std::shared_ptr
, которому принадлежит объект), автоматически уничтожает объект.