Должен ли я использовать общий ptr или уникальный ptr
я делал некоторые объекты, используя идиому pimpl, но я не уверен, использовать ли std::shared_ptr
или std::unique_ptr
.
Я понимаю, что std::unique_ptr
более эффективно, но это не столько проблема для меня, так как эти объекты в любом случае относительно тяжеловесны, поэтому стоимость std::shared_ptr
над std::unique_ptr
относительно незначителен.
в настоящее время я собираюсь с std::shared_ptr
просто из-за дополнительной гибкости. Например, используя std::shared_ptr
позволяет мне хранить эти объекты в hashmap для быстрого доступа, все еще имея возможность возвращать копии этих объектов вызывающим (поскольку я считаю, что любые итераторы или ссылки могут быстро стать недействительными).
однако эти объекты действительно не копируются, поскольку изменения влияют на все копии, поэтому мне было интересно, что, возможно, используя std::shared_ptr
и разрешение копий-это своего рода анти-шаблон или плохая вещь.
это правильно?
4 ответов
Я делал некоторые объекты, используя идиому pimpl, но я не уверен, следует ли использовать
shared_ptr
илиunique_ptr
.
наверняка unique_ptr
или scoped_ptr
.
Pimpl
- это не шаблон, а идиома, которая имеет дело с зависимостью от времени компиляции и бинарной совместимостью. Это не должно влиять на семантику объектов, особенно в отношении их поведения копирования.
вы можете использовать любой умный указатель, который вы хотите под капот, но те 2 гарантируют, что вы случайно не разделите реализацию между двумя различными объектами, поскольку они требуют сознательного решения о реализации конструктора копирования и оператора присваивания.
однако эти объекты действительно не копируются, поскольку изменения влияют на все копии, поэтому мне было интересно, что, возможно, используя
shared_ptr
и разрешение копий-это своего рода анти-шаблон или плохая вещь.
это не анти-шаблон, на самом деле, это шаблон: сглаживание. Вы уже используете его на C++ с голыми указателями и ссылками. shared_ptr
предложите дополнительную меру "безопасности", чтобы избежать мертвых ссылок, за счет дополнительной сложности и новых проблем (остерегайтесь циклов, которые создают утечки памяти).
не имеет отношения к Pimpl
Я понимаю
unique_ptr
более эффективен, но это не так много для меня, так как эти объекты относительно тяжеловес в любом случае так стоимостьshared_ptr
надunique_ptr
относительно незначителен.
если вы можете разложить какое-то состояние, вы можете взглянуть на Flyweight узор.
если вы используете shared_ptr
, Это не совсем классический pimpl
идиома (если вы не предпримете дополнительных шагов). Но настоящий вопрос
почему вы хотите использовать умный указатель для начала; это очень
ясно, где delete
должно произойти, и нет никакой проблемы
исключение безопасности или другое, чтобы быть обеспокоены. Максимально,
умный указатель сохранит вам строку или две кода. И
только один, который имеет правильную семантику boost::scoped_ptr
,
и я не думаю, что это сработает в данном случае. (IIRC, это требует
ля полный тип для создания экземпляра, но я мог бы быть
неправильный.)
важным аспектом идиомы pimpl является то, что ее использование должно быть прозрачный для клиента; класс должен вести себя точно так же, как если бы она была реализована классически. Это значит или блокировать копирование и назначение или реализация deep copy, если класс является неизменяемым (без функций-членов non-const). Ничего из обычного интеллектуальные указатели реализуют глубокую копию; вы можете реализовать один из конечно, но это, вероятно, по-прежнему требуется полный тип всякий раз, когда происходит копирование, что означает, что вам все равно придется обеспечить определенный пользователем конструктор копирования и оператор присваивания (поскольку они не могут быть inline). Учитывая это, вероятно, нет стоит потрудиться с помощью smart pointer.
исключение, если объекты являются неизменными. В этом случае
не имеет значения, является ли копия глубокой или нет, и shared_ptr
полностью справляется с ситуацией.
при использовании shared_ptr
(например, в контейнере, затем найдите это и верните его -значение), вы не вызываете копию объекта, на который он указывает, просто копию указателя со счетчиком ссылок.
это означает, что если вы изменяете базовый объект из нескольких точек, то вы влияете на изменения в экземпляр. Это именно то, для чего он предназначен, так что не некоторые анти-шаблон!
при передаче shared_ptr
(Как говорят комментарии), лучше пройти по ссылке const и скопировать (там, увеличив количество ссылок), где это необходимо. Что касается возврата, случае.
Да, пожалуйста, используйте их. Проще говоря, shared_ptr-это реализация умного указателя. unique_ptr-это реализация автоматического указателя: