Должен ли я использовать shared_ptr или unique_ptr?
У меня вопрос о std::unique_ptr
и std::shared_ptr
. Я знаю, что есть много вопросов о том, когда использовать какой, но я все еще не уверен, правильно ли я это понимаю. Я где-то читал, что выбор по умолчанию для интеллектуального указателя должен быть std::unique_ptr
, но, насколько я понимаю, для моих нужд я должен использовать std::shared_ptr
. Например, у меня есть:
class B;
class A
{
private:
B* b;
public:
B* getB();
};
A::getB()
{
return b;
}
Итак, в основном класс A
владеет указателем на объект типа B
и там есть метод, который возвращает этот указатель. Если я создаю getter, я предполагаю, что некоторый другой класс может получить доступ к этому указателю, и поэтому он должен быть shared_ptr
вместо unique_ptr
. Я прав, или я еще не понял?
Ответы
Ответ 1
Короткий ответ: зависит.
Это зависит от того, может ли храниться/использоваться указатель, возвращаемый getB
, когда владелец A вышел из сферы действия. Разница в том, что вы не владеете не тем количеством указателей, которое у вас есть.
- Если A все еще существует, когда вы используете результат
getB
, вы можете сохранить unique_ptr
и вернуть простой указатель (или ссылку, если getB
никогда не сможет вернуть nullptr
). Это выражает "A владеет B, и никто другой не делает".
- Если A может выйти из области видимости, пока вы используете/удерживаете результат
getB
, но B должен выйти из области действия вместе с (или вскоре после) A, сохранить shared_ptr
и вернуть weak_ptr
.
- Если возможно, что многие объекты, включая вызывающих абонентов
getB
, могут удержаться на B и нет четкого одиночного владельца, сохранить и вернуть shared_ptr
s.
Ответ 2
Предположим для примера, что действительно нужен указатель, и просто B b;
не разрезает его (возможно, B является, например, полиморфным).
Сценарий alpha
Итак, A является владельцем B.
private:
std::unique_ptr<B> b;
И getB
дает представление об этом.
public:
B& getB();
B& A::getB()
{
return *b;
}
Сценарий бета
A является одним из владельцев B.
private:
std::shared_ptr<B> b;
И А может дать право владеть этим B другим.
public:
std::shared_ptr<B> getB();
std::shared_ptr<B> A::getB()
{
return b;
}
Ответ 3
Вы возвращаете пустой указатель, а не shared_ptr
, поэтому использование общего указателя ничего не решит. Верните a shared_ptr
или используйте unique_ptr
. Постарайтесь подумать о том, как можно реализовать shared_ptr
, и я считаю, что это должно сделать мою мысль ясной.
Ответ 4
Я думаю, что ты прав.
Если бы вы указали только указатель B
как частный член в A
, я бы использовал std::unqiue_ptr
.
Ответ 5
В вопросе не хватает информации.
Интеллектуальные указатели захватывают и реализуют семантику владения. Если объекту A
принадлежит объект B
, поэтому уничтожение A
должно уничтожить B
, а затем использовать unique_ptr
. Но unique_ptr
здесь не делает хорошего типа возврата. Это будет только член, и вы все равно вернете пустой указатель.
Если получение B
означает, что клиент может продолжать использовать B
неопределенно, используйте shared_ptr
, потому что это будет совместное владение.