Должен ли я преобразовать shared_ptr в weak_ptr при передаче в метод? - PullRequest
8 голосов
/ 23 марта 2011

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

У нас есть несколько методов, таких как

 void doSomething(shared_ptr<MyClass> ptr)
 {
      //doSomething() is a member function of a class, but usually won't store the ptr
      ptr->foo();
      ...
 }

После обнаружения первых (косвенных) циклических зависимостей я бы хотел исправить ошибки в нашем проекте.Но я не совсем уверен, как.Есть ли какая-либо выгода в изменении метода с

 void doSomething(weak_ptr<MyClass> ptr)
 {
      shared_ptr<MyClass> ptrShared = ptr.lock();
      ptrShared->foo();
      ...
 }

?

Я также сбит с толку, потому что некоторые люди говорят (включая руководство по стилю Google), что, во-первых, важнополучить правильное владение (что, вероятно, будет означать введение многих weak_ptrs, например, в примере с методами, описанными выше, но также и для многих переменных-членов, которые у нас есть).Другие говорят (см. Ссылки ниже), что вы должны использовать weak_ptr для разрыва циклических зависимостей.Однако обнаружить их не всегда легко, поэтому мне интересно, действительно ли мне следует использовать shared_ptr, пока я не столкнусь с проблемами (и не пойму их), а затем исправлю их?

Спасибо за ваши мысли!

См. Также

Ответы [ 4 ]

6 голосов
/ 23 марта 2011

Мы четко не определили право собственности.

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

4 голосов
/ 23 марта 2011

Нет смысла менять свой дизайн выше с shared_ptr на weak_ptr.Право владения заключается не в использовании слабых_портров, а в том, чтобы управлять тем, кто хранит разделяемый_птр в течение значительного периода времени.Если я передам метод shared_ptr методу, при условии, что я не храню этот файл shared_ptr в поле моего объекта как части этого метода, я не изменил, кому принадлежат эти данные.

По моему опыту,причина для использования слабого_птр заключается в том, что у вас обязательно должен быть цикл указателей, и вам нужно разорвать этот цикл.Но сначала вы должны подумать, можете ли вы изменить свой дизайн, чтобы исключить цикл.

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

3 голосов
/ 23 марта 2011

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

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

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

2 голосов
/ 23 марта 2011

Некоторые люди правы: сначала вы должны иметь очень четкое представление о владении объектами в вашем проекте.

shared_ptrs shared , то есть «принадлежит сообществу».Это может быть или не быть желательным.Поэтому я бы посоветовал определить модель владения, а затем не злоупотреблять семантикой shared_ptr и использовать простые указатели всякий раз, когда владение не должно быть «разделено» более.

...