Search code examples
c++c++11scopeunique-ptr

When does a unique_ptr returned by a function (via std::move) go out of scope


I am working with a large object that is stored in a shared memory region, and is returned by a getter. I was running into issues where returning the object by-value was blowing the stack due to the size of the object. To avoid this, I decided to return a unique_ptr to a copy of the object on the heap, which I want the calling function to be able to use as a local variable. See my example code below:

Note: The codebase I am working on is C++11, not C++14, so I cannot use std::make_unique

#include <memory>
struct AbsoluteUnit {
    char bigChungus[10000000];
    int bigChungusSize;
};
AbsoluteUnit g_absUnit;

std::unique_ptr<AbsoluteUnit> getAbsoluteUnit() {
    return std::move(std::unique_ptr<AbsoluteUnit>(new AbsoluteUnit(g_absUnit)));
}

void Example1()
{
    std::unique_ptr<AbsoluteUnit> absUnitPtr = getAbsoluteUnit();
    AbsoluteUnit& absUnit = *absUnitPtr.get();
    ///
    /// Some other code
    ///
}

void Example2()
{
    AbsoluteUnit& absUnit = *getAbsoluteUnit().get();
    ///
    /// Some other code
    ///
}

My question is: In Example2, when does the unique_ptr go out of scope?

In Example1 I am storing the unique_ptr in a local variable, so I would expect it to go out of scope when the function exits. But in Example2, I am not creating a local variable for it, so what happens to the unique_ptr after that line executes? Is it still scoped to the function, or does it immediately go out of scope?


Solution

  • The get() member function returns the pointer to the AbsoluteUnit object managed by the std::unique_ptr<AbsoluteUnit> that getAbsoluteUnit() returns.

    That managed AbsoluteUnit object is then bound to the reference absUnit:

    AbsoluteUnit& absUnit = *getAbsoluteUnit().get();
    

    However, the std::unique_ptr ceases to exist just after this statement above, and therefore so does the managed AbsoluteUnit object. So, absUnit becomes a dangling reference.


    If you want to avoid working with the pointer syntax, you could write instead:

    const std::unique_ptr<AbsoluteUnit> ptr = getAbsoluteUnit();
    AbsoluteUnit& obj = *ptr;
    // ... use obj instead of ptr
    

    or even more concise with auto:

    const auto ptr = getAbsoluteUnit();
    auto& obj = *ptr;
    // ... use obj instead of ptr