我该使用 shared_ptr 还是 unique_ptr?

29

我对std::unique_ptrstd::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。我是正确的吗,还是我还没理解?


4
如果需要共享指针,请使用 std::shared_ptr。如果不需要共享指针,请使用 std::unique_ptr - Some programmer dude
可能是重复的问题,与https://dev59.com/p2w15IYBdhLWcg3wCXKJ和/或https://dev59.com/1nRB5IYBdhLWcg3wn4bb相同。 - Arne Mertz
1
@JoachimPileborg 如果他像那样返回一个裸指针,使用shared_ptr就没有意义了。 - Ivaylo Strandjev
5个回答

26

简短回答:取决于情况。

这取决于当所有者A已经超出范围时,getB返回的指针是否可能被存储或使用。区别在于所有权而不是你拥有多少指针。

  • 如果使用getB的结果时A仍然存在,则可以存储unique_ptr并返回一个普通指针(如果getB永远不会返回nullptr则返回引用)。这表示"A拥有B,没有其他人拥有"。
  • 如果当你使用/持有getB的结果时,A可能已经超出范围,但是B应该与A一起超出范围(或者很快超出范围),则存储shared_ptr并返回weak_ptr
  • 如果可能有许多对象(包括getB的调用者)可能持有B,并且没有明确的单个所有者,则存储并返回shared_ptr

7

为了举例说明,假设需要一个指针,仅仅使用B b;是不够的(例如B是多态的)。

场景alpha

因此,A是B的所有者。

private:
   std::unique_ptr<B> b;

getB提供了B的视图。

public:
   B& getB();


B& A::getB()
{
   return *b;
}

场景beta

A是B公司的其中一个拥有者。


注:其中一个拥有者意味着A与其他人共同拥有B公司。
private:
   std::shared_ptr<B> b;

同时,A可以将B的所有权转让给其他人。

public:
   std::shared_ptr<B> getB();


std::shared_ptr<B> A::getB()
{
   return b;
}

1
场景alpha没有考虑到b可能为空的情况。它依赖于这种可能性和返回的ptr/ref的使用,如果getB应该返回一个引用、一个普通指针或者一个weak_ptr,后者当然需要存储一个shared_ptr - Arne Mertz

2

你返回的是裸指针,而不是 shared_ptr,因此使指针共享将解决不了任何问题。要么返回一个 shared_ptr,要么使用 unique_ptr。尝试思考如何可能实现 shared_ptr,我相信这应该可以说明我的观点。


2

我认为你是正确的。 如果你只将B指针作为A的私有成员存储,我认为我会使用std::unique_ptr


1
问题中没有足够的信息。
智能指针捕获并实现所有权语义。如果 A 对象拥有 B 对象,因此销毁 A 应该销毁 B,则使用 unique_ptr。但是,在这里使用 unique_ptr 不是一个好的返回类型。它只会成为成员,您仍将返回裸指针。
如果获取 B 意味着客户端可以继续无限期使用 B,则使用 shared_ptr,因为那将是共享所有权。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接