Есть ли причины не использовать Boost :: shared_ptrs? - PullRequest
2 голосов
/ 26 февраля 2009

Я задал пару вопросов ( здесь и здесь ) об управлении памятью, и неизменно кто-то предлагает мне использовать boost :: shared_ptrs.

Учитывая, насколько они полезны, я серьезно подумываю над тем, чтобы переключить все мое приложение на использование boost :: shared_ptrs.

Однако, прежде чем я прыгну обеими ногами и сделаю это, я хотел спросить: есть ли у кого-нибудь плохой опыт с boost :: shared_ptrs? Есть ли какие-то подводные камни в их использовании, которые я должен остерегаться?

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

Ответы [ 4 ]

4 голосов
/ 26 февраля 2009

Недостатком является то, что они не бесплатны. Вам особенно не следует использовать shared_ptr / shared_array, когда scoped_ptr / scoped_array (или обычное распределение стека) подойдет. Вам нужно будет вручную прерывать циклы с помощью weak_ptr, если у вас есть. Векторный вопрос, на который вы ссылаетесь, - это один из случаев, когда я мог бы получить shared_ptr, второй вопрос - нет. Не копирование - это преждевременная оптимизация, особенно если строковый класс уже делает это за вас. Если к строковому классу подсчитывают ссылки, он также сможет правильно реализовать COW, что на самом деле невозможно сделать с помощью подхода shared_ptr<string>. Использование shared_ptr willy-nilly также представит «трение интерфейса» с внешними библиотеками / apis.

2 голосов
/ 26 февраля 2009

Повышение общих указателей или любой другой метод управления памятью в C ++ не является панацеей. Там нет замены для тщательного кодирования. Если вы погрузитесь в использование boost :: shared_ptr, помните о владении объектом и избегайте циклических ссылок. Вам нужно будет явно прерывать циклы или использовать boost :: weak_ptr, где это необходимо.

Также будьте осторожны, чтобы всегда использовать boost :: shared_ptr для экземпляра с момента его выделения. Таким образом, вы уверены, что у вас не будет свисающих ссылок. Один из способов обеспечить это - использовать фабричные методы, которые возвращают ваш вновь созданный объект в shared_ptr.

typedef boost::shared_ptr<Widget> WidgetPtr;
WidgetPtr myWidget = Widget::Create();
1 голос
/ 06 февраля 2013

Я часто использую shared_ptr.

Поскольку Shared_ptr копируется по значению, вы можете понести затраты на копирование как значения указателя, так и счетчика ссылок, но если используется boost :: intrusive_ptr, счетчик ссылок должен быть добавлен в ваш класс, и нет дополнительные издержки выше, чем при использовании необработанного указателя.

Однако, по моему опыту, более чем в 99% случаев издержки на копирование экземпляров boost :: shared_ptr по всему коду незначительны. Обычно, как отметил С. А. Р. Хоар, преждевременная оптимизация не имеет смысла - большую часть времени другой код использует значительно больше времени, чем время для копирования небольших объектов. Ваш пробег может варьироваться. Если профилирование показывает, что копирование является проблемой, вы можете переключиться на навязчивые указатели.

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

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

Конечно, как уже упоминалось, в некоторых случаях использование scoped_ptr (или scoped_array) является правильным выбором. Если pointee не является общим, не используйте общие указатели!

Наконец, самый последний стандарт C ++ предоставляет шаблон std :: tr1 :: shared_ptr, который в настоящее время используется на большинстве платформ, хотя я не думаю, что существует тип навязчивого указателя для tr1 (или, скорее, но я не слышал об этом сам).

0 голосов
/ 26 февраля 2009

Динамические накладные расходы памяти (т. Е. Дополнительные выделения) плюс все накладные расходы, связанные с умными указателями с подсчетом ссылок.

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