буст, общий птр против слабого птр? Что использовать, когда? - PullRequest
42 голосов
/ 10 января 2010

В моем текущем проекте я использую boost::shared_ptr довольно широко.

Недавно мои товарищи по команде также начали использовать weak_ptr. Я не знаю, какой и когда использовать.

Кроме того, что мне делать, если я хочу преобразовать weak_ptr в shared_ptr. Влияет ли установка блокировки на weak_ptr для создания shared_ptr на мой код в другом потоке?

Ответы [ 4 ]

70 голосов
/ 10 января 2010

В общем и целом,

Сильные указатели гарантируют собственную действительность. Используйте их, например, когда:

  • Вы владеете объектом, на который указывает; Вы создаете это и уничтожаете это
  • У вас нет определенного поведения, если объект не существует
  • Вы должны убедиться, что объект существует.

Слабые указатели гарантия зная свою действительность. Используйте их, например, когда:

  • Вы получаете к нему доступ, но он не ваш.
  • Вы определили поведение, если объект не существует

Lock () для слабого указателя возвращает сильный указатель; Вот как вы получаете доступ к слабому указателю. Если объект больше не действителен (он был удален и т. Д.), То сильный указатель будет равен NULL, в противном случае он будет указывать на объект. Вам нужно будет это проверить.

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

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

Там также производительность и круговые зависимости, упомянутые в других ответах.

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

22 голосов
/ 10 января 2010

Используйте weak_ptr, когда создаваемые вами объекты содержат циклические ссылки, т.е. shared_ptr на объект с shared_ptr обратно на себя. Это связано с тем, что shared_ptr не может обрабатывать циклические ссылки - когда оба объекта выходят из области видимости, взаимные ссылки означают, что они не являются "сборщиком мусора", поэтому память теряется и возникает утечка памяти. Поскольку weak_ptr не увеличивает счетчик ссылок, проблема циклического задания не возникает. В общем, это также означает, что если вы просто хотите взять указатель на что-то, что подсчитано, и не хотите увеличивать счетчик ссылок, используйте weak_ptr.

В противном случае вы можете использовать shared_ptr.

Для получения дополнительной информации обратитесь к документации Boost .

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

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

Есть две причины использовать слабый указатель:

  1. для устранения стоимости увеличения / уменьшения счетчика ссылок; однако вы не должны этого делать, потому что это подвержено ошибкам и на самом деле не экономит много времени
  2. В структурах бухгалтерских данных, например у вас есть индекс всех объектов Foo, которые «живы», т. е. используются где-то еще, и вы не хотите поддерживать Foo в индексе, если все «реальные» использования закончились. Это основной реалистичный вариант использования слабых указателей. Конечно, существуют и другие.

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

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

0 голосов
/ 10 января 2010

Вероятно, вам вообще не следует пытаться использовать слабые указатели, если вы не пытаетесь реализовать сборщик мусора, что не является горячей идеей в C ++, потому что слишком сложно отслеживать все, что может пойти не так, как надо. 1001 *

...