Boost, shared ptr Vs weak ptr? Что использовать, когда?

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

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

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

Ответы

Ответ 1

В общем и сводке

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

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

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

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

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

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

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

В других ответах также упоминаются характеристики производительности и круговой зависимости.

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

Ответ 2

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

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

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

Ответ 3

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

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

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

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

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

Ответ 4

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