Visual C ++ лучшие практики управления памятью - PullRequest
3 голосов
/ 11 февраля 2011

Я старый программист на C # и программист на C (без динамического выделения памяти), но хотел бы немного узнать о программировании на Visual C ++. Вопрос, который меня беспокоит, связан с управлением памятью в C ++. В C # сборщик мусора заботится об управлении памятью, но в C ++ необходимо, чтобы были установлены некоторые правила относительно того, кто отвечает за освобождение выделенной памяти. У меня есть несколько типичных сценариев из C #:

  1. Объект помещен в какой-то контейнер. Кто отвечает за освобождение памяти. Что если несколько классов используют один и тот же объект?

  2. Заводская модель. Мне нравится использовать иерархию классов, где родительский класс имеет метод для создания дочерних объектов?

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

Я хотел бы услышать несколько хороших советов по этому поводу.

Ответы [ 2 ]

12 голосов
/ 11 февраля 2011

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

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, которому принадлежит объект), автоматически уничтожает объект.

3 голосов
/ 11 февраля 2011

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

Википедия - хорошее место для начала чтения: RAII в Википедии

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