DEV Community

Cover image for C++ unique_ptr: reset() vs release() vs std::move
elysianx
elysianx

Posted on

C++ unique_ptr: reset() vs release() vs std::move

When you first learn std::unique_ptr, three things confuse almost everyone: release(), reset(), and std::move. They all look like they "give something up", but they do very different things. This post explains what each one really does, with short examples.


1. The key to understanding release()

release() means: "I don't want to manage this object anymore."

It does not delete the object. It just gives up ownership and hands the raw pointer back to you. After the call, the smart pointer is empty (get() returns nullptr), and you are now responsible for deleting the object.

Parameters
(None)

Return value
The raw pointer to the managed object, or nullptr if there was no managed object.

Example

#include <memory>
#include <iostream>

int main(){
    std::unique_ptr<int> ptr = std::make_unique<int>(100);
    int* raw = ptr.release(); // ptr gives up ownership, ptr is empty now
    if(!ptr)
        std::cout<< *raw << std::endl;
    delete raw; // we must delete raw manually
}
Enter fullscreen mode Exit fullscreen mode

Warning: release() is rarely what you want:

  1. If you forget to capture the returned raw pointer, the object leaks immediately.
  2. After taking the raw pointer, you must remember to delete it yourself — you are back to manual raw-pointer management.
  3. The one legitimate use: handing the object to a legacy C API that requires a raw pointer and promises to take ownership.

2. The right way to use reset()

reset() replaces the managed object.

Called with no argument, ptr.reset() deletes the object it owns and becomes empty. If you pass in a new pointer, the old object is destroyed first, and the smart pointer then takes ownership of the new one.

Parameters
ptr - (optional) pointer to a new object to manage

Example

#include <memory>
#include <iostream>

int main(){
    std::unique_ptr<int> ptr = std::make_unique<int>(100);

    ptr.reset();  // delete the original object, ptr is empty.

    ptr.reset(new int(10)); // delete the old object, manage the new pointer.
}
Enter fullscreen mode Exit fullscreen mode

3. Comparing release() and reset()

  • release(): does not delete the old object — it hands the raw pointer back to you
  • reset(): deletes the old object (if any), then manages the new pointer you pass in
  • Both make the smart pointer lose control of the old resource; the difference is who deletes the object and when
release() reset()
Old object destroyed? No — you must delete it yourself Yes, immediately
Smart pointer after call empty manages the new pointer (or nothing)
Returns the raw pointer nothing

4. How std::move fits in

std::move does not move anything by itself. It only marks an object as "moved-from" — a permission slip saying "you may take this object's resources instead of copying them".

Parameters
ob - the object to be moved

Example

class MyClass{
    std::string data;
public:
    MyClass(std::string&& str) : data(std::move(str)) {}
};
Enter fullscreen mode Exit fullscreen mode
std::vector<std::string> v;
std::string temp = "example";
v.push_back(std::move(temp));
Enter fullscreen mode Exit fullscreen mode
#include <memory>
#include <iostream>

int main(){
    std::unique_ptr<int> ptr1(new int(10));
    std::unique_ptr<int> ptr2 = std::move(ptr1);
    if(!ptr1)
        std::cout<< "ptr1 is empty" << std::endl;
    if(ptr2)
        std::cout<< "ptr2 owns the resource and value is: "<<*ptr2 << std::endl;
}
Enter fullscreen mode Exit fullscreen mode

Why is std::move so common with smart pointers?
std::unique_ptr has exclusive ownership: it cannot be copied, because two owners would delete the same object twice. So the only way to transfer ownership between unique_ptrs is std::move.


References

Top comments (0)