Search code examples
c++c++11c++14shared-ptrunique-ptr

Constructor dependency injection: unique_ptr + move vs shared_ptr


Let's assume we have something like this:

struct Complex{
    Complex(Part1 p1, Part2 p2, Part3 p3)
}

Part1 p1; 
Part2 p2;
Part3 p3; 

However passing copies is not effective, so we need to move to pointers. The questions is what type to use — unique_ptr or shared_ptr

At first glance, since Complex is a real owner of p1, p2, p3, it seems unique_ptr is better; however, since it could not be copied, we would need to use std::move.

So my question is — what is the better way for this case, create unique_ptr out of Part, and then use move in Complex's constructor, or create shared_ptr from the beginning and use shared_ptr instead?


Solution

  • The best solution would be to make the Part types cheap to move, and move them in. However, if that is not an option, you will have to resort to managing them dynamically.

    As you say, Complex owns the parts, so it should accept them as std::uniqe_ptr<Part> and move these pointers into itself. Moving a std::unique_ptr is dirt cheap: it probably involes just two pointer assignments.

    On the other hand, using std::shared_ptr and copying that involves an unnecessary atomic increment (for creating the copy) and decrement (for destroying the original). Atomic operations are certainly far from cheap for today's cache-heavy, multi-core processors.

    So just stick to the intended semantics of your code (unique ownership, which is idiomatically expressed by std::unique_ptr), and you will get good performance as a bonus.