Как я могу обнаружить или избежать циклических ссылок с std::shared_ptr?

Я знаю что есть weak_ptr разорвать цикл, но это исправление после обнаружения проблемы. Существует ли шаблон или инструмент, который можно использовать для обнаружения или предотвращения циклических ссылок?

4 ответа

Решение

Я бы сильно повторил сказанное Sellibitze и переосмыслил дизайн. Если то, что у вас действительно есть, является односторонним владением и просто наблюдением в противоположном направлении, рассмотрите слабый_тр. Это позволяет вам проверить, является ли объект живым, но не поддерживает его, просто потому что у вас есть указатель на него.

Вы избегаете этого по замыслу. Как замечательно отметил Стефан Т. Лававей на конференции GoingNative2012 (вы можете посмотреть видео онлайн), "владение" - это ориентированный ациклический граф, DAG. В DAG нет циклов. Если ваш график владения не DAG, ваш дизайн… сомнителен, потому что A, владеющий B, и B, владеющий A, не имеет смысла. Но shared_ptr - это "указатель общего владения". Объекту или области видимости, содержащему такой указатель, принадлежит объект pointee. Попробуйте мыслить с точки зрения графиков собственности.

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

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

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

Я бы рекомендовал это только для большой базы кода с интенсивным shared_ptr использование и неспособность контролировать все аспекты дизайна. Для других случаев просто используйте рекомендацию @sellibitze.

Другие вопросы по тегам