Search code examples
c++smart-pointersunique-ptr

Returning unique_ptr private member data without transferring ownership


Context

The error below appears to be telling me that I can not return my unique_ptr called m_head from this get function. I just want to return my unique_ptr m_head without transferring ownership.

I've been avoiding raw pointers completely since introduced to smart pointers since raw pointers are not exception safe, have the memory management overhead and other issues I've been aware of. Maybe there are cases like this where I should use them briefly contained in a small scope?

In this I think instead of my current approach I need to transfer ownership. I should instead get the object managed by the unique_ptr, create a new shared_ptr to manage the object, then return the shared_ptr, but need some confirmation. I think this may be the case because the std::unique_ptr docs say:

unique_ptr objects own their pointer uniquely: no other facility shall take care of deleting the object, and thus no other managed pointer should point to its managed object, since as soon as they have to, unique_ptr objects delete their managed object without taking into account whether other pointers still point to the same object or not, and thus leaving any other pointers that point there as pointing to an invalid location.

Error

 `function "std::unique_ptr<_Ty, _Dx>::unique_ptr(const std::unique_ptr<_Ty, _Dx> &) 
 [with _Ty=mrobsmart::LinkedList::Node, _Dx=std::default_delete<mrobsmart::LinkedList::Node>]" 

 (declared at line 2337 of "C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\VC\Tools\MSVC\14.15.26726\include\memory")

 cannot be referenced  -- it is a deleted function

Code

#include <memory>

class LinkedList
{
    private:
        std::unique_ptr<Node> m_head;

    public:
        LinkedList(int data) {
            m_head = std::make_unique<Node>(data);
        }

        const std::unique_ptr<Node> get_head() { return m_head; }
};

Solution

  • I just want to return my unique_ptr m_head without transferring ownership.

    That's not possible. unique_ptr is designed around the behavior that every move transfers its ownership.

    Note, I've been avoiding raw pointers completely since introduced to smart pointers since raw pointers are not exception safe, have the memory management overhead and other issues I've been aware of, but maybe there are cases like this where I should use them briefly contained in a small scope?

    Raw pointers are not evil. Using them as pure references/indirections is a perfectly valid use case -- there is no ownership, memory management or exception safety involved.

    Of course, it's also possible to return a C++ reference. Whether you choose a pointer or a reference can depend on whether the value can be null, but ultimately is also a question of code style.

    So, either of those (important: const-qualify the function):

        const Node* get_head() const { return m_head.get(); }
        const Node& get_head() const { return *m_head; }