усиление, общий ptr против слабого ptr?Что и когда использовать?

StackOverflow https://stackoverflow.com/questions/2036182

Вопрос

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

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

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

Это было полезно?

Решение

В общих чертах и резюме,

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

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

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

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

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

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

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

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

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

Другие советы

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

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

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

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

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

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

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

Н.Б.циклическим объектам не нужны слабые указатели, вы можете использовать вместо них готовые обычные указатели в большинстве правильно сконструированных программ.Однако слабые указатели менее рискованны.

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top