1

I have a reference to my object of type MyType, but I need to call a function, say myFunction that takes a std::unique_ptr<MyType>. What is the correct way to call myFunction? My attempt below seems to cause an "invalid pointer" error:

#include <memory>

class MyType {};
MyType myGlobalObj;

MyType& myGetter () {
    return myGlobalObj;
}

void myFunction (std::unique_ptr<MyType> ptr) {
    // Do important stuff
}

int main () {
    MyType& myObj = myGetter();
    std::unique_ptr<MyType> myPtr;
    myPtr.reset(&myObj);
    myFunction(std::move(myPtr)); // This causes "invalid pointer" at run time.
    myPtr.release();
    return 0;
}
Antonio
  • 355
  • 1
  • 2
  • 13
  • 2
    `myPtr.reset(&myObj);` - don't do that. unique pointers and shared pointers are for managing *dynamic* ownership. `myGlobalObject` cannot be used in a unique-ptr paradigm. There is no way to 'fake' a unique-ptr hosting that thing, much less deliver said-same to a by-value parameter expecting to take (and ultimately release) ownership of it. – WhozCraig May 06 '22 at 10:15
  • `myFunction` signature is saying "You need to give me a `unique_ptr` that I can become the owner of, and you're not getting it back because I'm going to consume it." You can call the function this way: `myFunction(std::make_unique(myGetter()));` which will make a copy of the object wrapped that into a unique_ptr smart pointer. – Eljay May 06 '22 at 11:53

1 Answers1

3

What you are trying to do is not possible without either doing a (deep-)copy of myGlobalObj or modifying myFunction.

A std::unique_ptr takes ownership of the memory that is used to store the contained object. That means that the std::unique_ptr may free (or reallocate, or whatever) the memory that it 'owns'. What it would do in your case: As soon as the ptr variable goes out of scope at the end of myFunction, it will attempt to free the memory that it points to. Since myGlobalObj is a global variable, its memory may never be freed (before a controlled shutdown of your program…)

Thus, you should not ever wrestle a global object into a std::unique_ptr (or a std::shared_ptr, for that matter). If there is really no way of refactoring that method to take anything else than a std::unique_ptr, you must make a copy (on the heap!) of myGlobalObj, wrap that into a std::unique_ptr, and pass it to myFunction. Keep in mind that this way, myFunction loses the ability to modify myGlobalObj.

Lukas Barth
  • 2,734
  • 18
  • 43