29

I have a question about std::unique_ptr and std::shared_ptr. I know there are loads of questions about when to use which one, but I'm still not sure if I understand it correctly. I read somewhere that the default choice for smart pointer should be std::unique_ptr, but as I understand it, for my needs I should rather use std::shared_ptr. For example, I have:

class B;
class A
{
private:
   B* b;
public:
   B* getB();
};

A::getB()
{
   return b;
}

So basically class A owns pointer to object of type B and there's a method which returns this pointer. If I create getter, I assume that some other class can access this pointer and therefore it should be shared_ptr instead of unique_ptr. Am I right, or I don't get it yet?

Kijewski
  • 25,517
  • 12
  • 101
  • 143
dziwna
  • 1,212
  • 2
  • 14
  • 25
  • 4
    If you need to share a pointer, use `std::shared_ptr`. If you _don't_ need to share a pointer, use `std::unique_ptr`. – Some programmer dude Feb 14 '13 at 09:37
  • possible dup of http://stackoverflow.com/questions/6876751/differences-between-unique-ptr-and-shared-ptr and/or http://stackoverflow.com/questions/569775/smart-pointers-boost-explained – Arne Mertz Feb 14 '13 at 09:37
  • 1
    @JoachimPileborg still if he returns a bare pointer like he does there is no sense in using a `shared_ptr` – Ivaylo Strandjev Feb 14 '13 at 09:38

5 Answers5

26

Short answer: depends.

It depends on if the pointer returned by getB may be stored/used somewhere while the owning A has gone out of scope. The difference is about ownership not about how many pointers you do have.

  • If the A still exists when you use the result of getB , you can store a unique_ptr and return a plain pointer (or a reference if getB can never return nullptr). That expresses "A owns B, and no-one else does".
  • If the A might go out of scope while you are using/holding the result of getB, but the B should go out of scope together with (or shortly after) the A, store a shared_ptr and return a weak_ptr.
  • If possibly many objects, including the callers of getB, may hold on to the B and there is no clear single owner, store and return shared_ptrs.
user703016
  • 37,307
  • 8
  • 87
  • 112
Arne Mertz
  • 24,171
  • 3
  • 51
  • 90
7

Let's assume for the sake of example that a pointer is really needed and just B b; doesn't cut it (maybe B is polymorphic, for example).

Scenario alpha

So, A is the owner of a B.

private:
   std::unique_ptr<B> b;

And getB provides a view of that B.

public:
   B& getB();


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

Scenario beta

A is one of the owners of a B.

private:
   std::shared_ptr<B> b;

And A can give ownership of that B to others.

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


std::shared_ptr<B> A::getB()
{
   return b;
}
R. Martinho Fernandes
  • 228,013
  • 71
  • 433
  • 510
  • 1
    Scenario alpha does not account for the possibility that b is NULL. It depends on that possibility and on the usage of the returned ptr/ref, if `getB` should return a reference, a plain pointer or a `weak_ptr`, the latter of course demands a stored `shared_ptr` – Arne Mertz Feb 14 '13 at 09:47
2

You return a bare pointer, not a shared_ptr, so making the pointer shared will solve nothing. Either return a shared_ptr, or use a unique_ptr. Try to think of how can possible shared_ptr be implemented and I believe this should make my point clear.

Ivaylo Strandjev
  • 69,226
  • 18
  • 123
  • 176
2

I think you are right. If you would only story the B pointer as private member in A, I think I would use an std::unqiue_ptr.

tehlexx
  • 2,821
  • 16
  • 29
1

There isn't enough information in the question.

Smart pointers capture and implement ownership semantics. If the A object owns the B object, so destroying the A should destroy the B, then use unique_ptr. But unique_ptr doesn't make a good return type here. It would only be the member and you would still return a bare pointer.

If getting the B means the client can continue using the B indefinitely, then use shared_ptr, because that would be shared ownership.

Potatoswatter
  • 134,909
  • 25
  • 265
  • 421