c++c++11cpp-core-guidelines

CppCoreGuidlines R.33 Why pass `unique_ptr` by reference?


The CppCoreGuidlines rule R.33 suggests to

Take a unique_ptr<widget>& parameter to express that a function reseats the widget.

Reason Using unique_ptr in this way both documents and enforces the function call’s reseating semantics.

Note “reseat” means “making a pointer or a smart pointer refer to a different object.”

I don't understand why we should pass by reference when reseat means "making a pointer or a smart pointer refer to a different object.”

When the function's purpose is to reseat/change the underlying object the pointer is pointing to, aren't we stealing the ownership from the caller this way and therefore should pass the unique_ptr by value, hence moving it and transferring ownership?

Is there an example that explains why passing a unique_ptr by reference is recommended?


Solution

  • When the function's purpose is to reseat/change the underlying object the pointer is pointing to, aren't we stealing the ownership from the caller this way

    No. Neither when we "reseat" a pointer, nor when we change the pointed object, do we take ownership of the pointer i.e. we aren't transferring the ownership.

    Is there an example that explains why passing a unique_ptr by reference is recommended?

    Here is an example of a function that "reseats" a unique pointer:

    void reseat(std::unique_ptr<widget>& ptr) {
        ptr = std::make_unique<widget>();
    }
    

    If you tried to use a reference to const, then that wouldn't compile at all. If you tried to use a non-reference parameter, then the argument pointer wouldn't be modified and thus the behaviour wouldn't be as desired. The caller would be forced to move their pointer leaving it always null.

    You could modify the example to use a pointer to unique pointer, but references are recommended because it isn't possible to pass null by mistake. A reference wrapper would also work, but it would be unnecessarily complicated.

    In case we make it point somewhere else, what happens to the object it pointed before?

    If a unique pointer points to something other than null, then making it point elsewhere will cause the previously pointed object to be deleted.

    Aren't we leaking memory in this case?

    No.


    Note that the example is simple in order to be easy to understand. Typically I wouldn't recommend to write such function and instead considering to write a function that returns the new unique pointer, and let the caller "reseat" the pointer themselves. But that depends on details.