Search code examples
c++moveshared-ptrsmart-pointers

Move Constructor and = operator for Shared Pointer


Say, I have a class:

class GameObject ///header file
{
    ....
    std::shared_ptr<Transform> transform;
}
///cpp file
//Copy Ctor
GameObject::GameObject(const GameObject& rhs)
   :transform(rhs.transform)
{}
//Move CTor
GameObject::GameObject(GameObject&& rhs)
    :transform(std::move(rhs.transform))
{}
  1. Is this the correct to create a move constructor for a class that has a shared_ptr member variable? Or do I need to to call rhs.transform.reset() to de-allocate the rhs after the move?
  2. How about the copy constructor?
  3. Presumably, the copy and move assignments look basically the same as the ctors, just with a return *this at the end?

Solution

  • Your copy and move constructors are equivalent to the implicit ones. Remove them. You don't need to write them out explicitly as the copy and move constructor of the std::shared_ptr correctly implement both operations.

    Or do I need to to call rhs.transform.reset() to de-allocate the rhs after the move?

    No, the moved-from object will lose ownership after the move:

    shared_ptr(shared_ptr&& r) noexcept;
    template<class Y> shared_ptr(shared_ptr<Y>&& r) noexcept;
    

    Remark: The second constructor shall not participate in overload resolution unless Y* is convertible to T*.

    Effects: Move-constructs a shared_ptr instance from r. Postconditions: *this shall contain the old value of r. r shall be empty. r.get() == nullptr.

    As for the copy and move-assignment operators, they too will be equivalent. Move-assignment will correctly transfer ownership and the copy-constructor will perform a shallow copy so that both shared_ptrs have ownership.

    If a shallow copy (shared ownership) is really want you want, then shared_ptr is the correct tool. Otherwise I'd suggest using unique_ptr if you want to implement unique ownership.