web-dev-qa-db-ja.com

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のオブジェクトへのポインターを所有し、このポインターを返すメソッドがあります。ゲッターを作成する場合、他のクラスがこのポインターにアクセスできるため、shared_ptr の代わりに unique_ptr。私は正しいですか、それともまだわかりませんか?

25
dziwna

短い答え:場合によります。

所有するAがスコープ外に出たときに、getBによって返されたポインターがどこかに格納/使用されるかどうかによって異なります。違いはownershipについてであり、ポインタの数についてではありません。

  • getBの結果を使用するときにAがまだ存在する場合は、unique_ptrを格納してプレーンポインター(またはgetBnullptr)。それは「AはBを所有し、他の誰も所有しない」ことを表します。
  • getBの結果を使用/保持しているときにAがスコープ外になる可能性があるが、BがAと共に(またはその直後に)スコープ外になる場合は、shared_ptrを格納し、 weak_ptrを返します。
  • getBの呼び出し元を含む多くのオブジェクトがBを保持している可能性があり、明確な単一の所有者がいない場合、shared_ptrsを格納して返します。
24
Arne Mertz

例として、ポインタが本当に必要であり、B b;はそれをカットしません(たとえば、Bは多態性です)。

シナリオアルファ

つまり、Aはthe Bの所有者です。

private:
   std::unique_ptr<B> b;

そしてgetBはそのBのビューを提供します。

public:
   B& getB();


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

シナリオベータ

Aはの1つ Bの所有者です。

private:
   std::shared_ptr<B> b;

そして、AはそのBの所有権を他人に与えることができます。

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


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

shared_ptrではなく、ベアポインターを返すため、ポインターを共有にしても何も解決されません。 shared_ptrを返すか、unique_ptrを使用します。どのようにしてshared_ptrを実装できるかを考えてみてください。これで私のポイントが明確になると思います。

私はあなたが正しいと思います。 BのプライベートメンバーとしてAポインターのみをストーリー化する場合は、std::unqiue_ptrを使用すると思います。

2
tehlexx

質問に十分な情報がありません。

スマートポインターは、所有権のセマンティクスをキャプチャして実装します。 AオブジェクトがBオブジェクトを所有している場合、Aを破棄するとBが破棄され、unique_ptrを使用します。ただし、ここではunique_ptrは適切な戻り値の型にはなりません。それはメンバーだけであり、あなたはまだ裸のポインターを返します。

Bを取得すると、クライアントがBを無期限に使用し続けることができることを意味する場合は、shared_ptrを使用します。これは、所有権が共有されるためです。

2
Potatoswatter