В настоящее время я управляю жизненным циклом объектов в своем проекте вручную. Я рассматриваю возможность переключения на интеллектуальные указатели, в частности tr1 :: shared_pointer и tr1 :: weak_ptr. Тем не менее, я вижу пару проблем и хотел бы получить некоторый вклад в лучшие практики.Последствия владения моделью с помощью интеллектуальных указателей
Рассмотрим следующую диаграмму классов:
На этой диаграмме, толстые стрелки представляют ассоциации с семантикой собственности (источник отвечает за удаление цели или цели). Тонкие стрелки представляют ассоциации без права собственности.
Из того, что я понимаю, одним из способов реализации ассоциации с семантикой собственности было бы использовать tr1 :: shared_ptr (или их коллекцию). Другие ассоциации могут быть реализованы с использованием либо tr1 :: shared_ptr, либо tr1 :: weak_ptr. Первый запрещен, если это может привести к циклическим ссылкам, поскольку это предотвратит надлежащее выделение ресурсов.
Как вы можете видеть, существует круг ассоциаций между классами Edge и Side. Я могу легко сломать это, реализуя «левые» и «правильные» ассоциации от Edge to Side, используя tr1 :: weak_ptrs. Тем не менее, я бы предпочел использовать интеллектуальные указатели для документирования в коде семантики собственности ассоциаций. Поэтому я хотел бы использовать shared_ptrs только для ассоциаций, представленных толстыми стрелками на диаграмме, и weak_ptrs для всего остального.
Теперь мой первый вопрос: должен ли я использовать weak_ptrs либерально, как описано выше, или я должен использовать их как можно меньше (только для того, чтобы избежать циклических ссылок)?
Следующий вопрос: Предположим, у меня есть функция, которая вычисляет среднее значение множества вершин. Предположим далее, что я реализовал ассоциацию с многогранника его Вершины так:
class Vertex;
class Polyhedron {
protected:
std::vector<std::tr1::shared_ptr<Vertex> > m_vertices;
};
и что я реализовал ассоциацию с полутуши ее Вершины так:
class Vertex;
class Side {
protected:
std::vector<std::tr1::weak_ptr<Vertex> > m_vertices;
};
Обратите внимание, что множество вершин Сиды является подмножеством множества вершин многогранника. Теперь предположим, что у меня есть функция, которая вычисляет среднее значение набора вершин. Эта функция в настоящее время объявлен следующим образом:
const Vertex centerOfVertices(std::vector<Vertex*> vertices);
Теперь, если я представляю ассоциации, как указано выше, я вдруг понадобятся две функции, если я все понимаю правильно:
const Vertex centerOfVertices(std::vector<std::tr1::shared_ptr<Vertex> > vertices);
const Vertex centerOfVertices(std::vector<std::tr1::weak_ptr<Vertex> > vertices);
Потому что я не могу конвертировать между вектором shared_ptr и вектор weak_ptr. Это смешно для меня. Я хотел бы знать, какой подход я должен предпринять здесь, чтобы избежать такой ситуации.
Что вы имеете в виду «а' weak_ptr' не может быть преобразовано в 'shared_ptr'» ? Вызов 'lock()' на 'weak_ptr', и он дает вам' shared' –
. Я думаю, что это будет злоупотреблять 'shared_ptr', я не читал это внимательно, но это не похоже на что-либо на самом деле _shares_. Вместо этого используйте 'unique_ptr' и необработанные указатели и предоставляйте гарантии системам, которые вы даете (слабым) исходным указателям, к тому, что объект, на который они указывают, будет действителен во время их действия. – David
Думаю, я понял бы это намного лучше, если бы знал, что представляет собой «сторона». Это означает «лицо»? – Rook