У меня есть ориентированный ациклический граф, реализуемый классами Graph и Node. Каждый Node имеет список указателей на childern и список указателей на родителей. Недавно я добавил родителей, потому что некоторые алгоритмы требовали быстрого доступа к родительскому списку, а график небольшой, всего несколько соединений на node, поэтому проблем с памятью не возникает.
В списке Child используется std:: shared_ptr, так что узлы хранятся в памяти, по крайней мере, до тех пор, пока у них есть родители. Но я не хочу, чтобы Node владел родителями, поэтому я использовал weak_ptr для указателей на родителей.
Но тогда возникла проблема с алгоритмами. Алгоритм должен создать новый shared_ptr из weak_ptr, поэтому я не могу напрямую использовать operator ==, а использование стандартных функций, таких как std:: find(), требует записи лямбда-функции, которая называется my_weak_ptr.lock(), а затем сравнивает ее к некоторому shared_ptr.
Если я переключусь на shared_ptr, любая небольшая ошибка в коде, который может быть использован для удаления Node, может привести к утечке памяти. Или, если у меня есть указатель на Node, который уже удален, код сможет получить доступ к Node, который не должен существовать, поэтому найти некоторые ошибки могут значительно сложнее. Но работа с shared_ptr столь же безопасна, как и weak_ptr с точки зрения не разыменования/удаления/etc. когда не предполагается, (так что это лучше, чем исходный указатель на С++) и std:: find() можно использовать напрямую, поскольку shared_ptr может быть разыменован, в отличие от weak_ptr.
Существует ли здесь "лучший" дизайн, или это проблема этой конкретной ситуации, в зависимости от, например, сколько имеет значение, если я выполняю дополнительную операцию weak_ptr:: lock() или рискую найти труднодоступные ошибки?