Могу ли я использовать C ++ Boost shared_ptr для программирования, как если бы я программировал на Java, а не заботиться об управлении памятью? - PullRequest
6 голосов
/ 17 января 2010

Я давно программировал на C / C ++, и теперь мне нужна его эффективность для проекта, которым я занимаюсь.

Что я понимаю из этого shared_ptr, так это то, что он в основном удаляет объект, когда мне это нужно. Итак, если, например, у моего объекта есть вектор shared_ptr, мне не придется беспокоиться об итерациях по вектору и удалении каждого элемента в деструкторе? Другими словами, мне не нужно беспокоиться об управлении памятью, пока я их использую? Или я совершенно не понимаю этого? Звучит слишком хорошо, чтобы быть правдой.

Ответы [ 3 ]

11 голосов
/ 17 января 2010

Вы должны понимать, что совместно используемые указатели реализованы с использованием счетчика ссылок, это означает, что если у вас есть циклы в графе указателей, то объекты не будут освобождены. То есть, если a указывает на b, а b указывает на a, но ничто не указывает на a или b, то ни a, ни b не будут освобождены, поскольку у них обоих счетчик ссылок равен 1.

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

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

Кроме этого, да, они очень полезны для управления динамически размещаемыми объектами.

Редактировать: Еще один уловок (упомянутый на страницах поддержки) - избегать "временных" указателей shared_points:

func(A(), boost::shared_ptr<B>(new B));

потому что компилятору разрешено оптимизировать это как

tmp1 = new B;
tmp2 = A();
tmp3 = boost::shared_ptr<B>(tmp1)
func(tmp2,tmp3)

, что на первый взгляд может выглядеть нормально, но если A () генерирует исключение, то B выделяется, но shared_ptr еще не получил его, поэтому указатель никогда не освобождается.

6 голосов
/ 17 января 2010

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

Что еще более важно, похоже, что вы пытаетесь избежать разработки своего кода. В Java есть gc, поэтому вам не нужно беспокоиться об управлении памятью, но вы все равно должны быть обеспокоены временем жизни объектов. Если вам неясно, кому принадлежит то, что вы, вероятно, получите в результате запутанного дизайна.

C ++ дает вам множество опций, когда речь идет о времени жизни объекта, не каждый сложный объект нужно размещать в куче. shared_ptr следует использовать для объектов, которые требуют совместного владения (как следует из названия), но это должно быть положительным дизайнерским решением. Существуют лучшие способы владеть объектом, если не требуется совместное или передаваемое владение.

4 голосов
/ 17 января 2010

Здесь Имеется ли в C # эквивалент boost :: shared_ptr ? Я разместил некоторую информацию о различных стратегиях автоматического управления памятью. Это объясняет основные различия между ГХ и подсчетом ссылок.

Лишь немногие современные разработчики C ++ используют такие вещи, как ручное управление памятью (или ресурсами). Большинство из нас вместо этого используют идиому RAII (см. http://en.wikipedia.org/wiki/RAII),, т.е. некоторые служебные классы, которые помогают нам иметь дело с ресурсами.

Shared_ptr - отличный метод, который облегчает рутинные задачи по управлению памятью / ресурсами. Эта методика имеет некоторые недостатки (не может иметь дело с циклическими структурами, и имеет накладные расходы производительности как во времени, так и в пространстве. Для каждой операции над ссылками реализация теперь будет выполнять арифметическую операцию - и, в случае отсоединения, условную инструкцию. Кроме того, каждый объект должен быть расширен дополнительным полем для хранения счетчика).

Я недавно участвовал в довольно большом проекте (только моя часть содержит более двухсот классов), и я никогда (НИКОГДА) не использую оператор delete вручную. Такие утилиты облегчают кодирование, отладку, обслуживание и значительно сокращают затраты на разработку. В последнее время я участвовал в аналогичном проекте (с очень похожей бизнес-логикой и архитектурой), но в C #. И я могу вам сказать по-настоящему: они очень похожи (прежде всего потому, что автоматическое управление памятью в проекте C ++).

P.S. Не каждый программист C ++ знал, но shared_ptr может использовать в автоматическом управлении ресурсами (не только в автоматическом управлении памятью) с пользовательским удалением.

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