5

I (erroneously) had the following assignment in my program:

std::shared_ptr<SI::Program> m_program; // in class

m_program = std::make_unique<SI::Program>(); // in method

When I found this, I first wondered why this even compiles. It turns out the shared_ptr has a special move assignment operator for unique_ptr objects.

My question is, is this therefore always safe to do, or does it have any implications?

(Safe as for the code execution; it is obviously not safe for a code review...)

Felix Dombek
  • 11,461
  • 15
  • 67
  • 116
  • one reason to do this might be to take advantage of `unique_ptr`'s array specialization, which `shared_ptr` lacks. [This *does* create a safety problem though.](http://stackoverflow.com/questions/32483375/shared-ptr-from-unique-ptr-to-an-array) – jaggedSpire Aug 18 '16 at 15:43

2 Answers2

6

It is "safe" to do so in a sense that you won't have any double-deleting or other problems.

It is not OK to do so because:

  1. It's misleading - make_unique is used to make unique pointers, not shared.
  2. It's wasteful - make_unique will only allocate the object, not the associated control block. that will force the shared_ptr constructor to allocate the control block itself. std::make_shared allocate them both in one allocation, which is much more efficient.
David Haim
  • 23,138
  • 3
  • 38
  • 70
  • 1
    "*It's misleading - make_unique is used to make unique pointers, not shared.*" If the committee thought it was misleading to be able to upgrade unique ownership into shared ownership, they wouldn't have given `shared_ptr` a specific constructor to do exactly that. – Nicol Bolas Aug 18 '16 at 15:31
  • 1
    @NicolBolas The upgrading might generally be ok, but written like I did, it certainly has some WTF factor to it – Felix Dombek Aug 18 '16 at 15:34
5

Yes, that's perfectly safe; shared_ptr has a constructor that can transfer ownership from a unique_ptr by move. Though it's not as efficient as calling make_shared properly.

Nicol Bolas
  • 378,677
  • 53
  • 635
  • 829