Can a std::unique_ptr be reassigned such that its old value is destroyed *before* the new one is constructed?

I’m interested in updating an old personal project to modern C++. I appreciate how RAII simplifies cleanup: instead of making a new object and remembering to delete it before every return point in a function, just make_unique and it will be destroyed appropriately. But I have one nitpick when comparing the generated assembly.

Say there’s a class method that replaces one of its unique_ptr members with a new value:

// std::unique_ptr<int> MyClass::m_foo;
void MyClass::refresh_foo(int x) {
    m_foo = std::make_unique<int>(x * 3 + 5);
}

This will create a new int, assign it to m_foo, and then delete the old value of m_foo. But that’s not quite the same as the old behavior, which could delete the old value, then create a new one and assign it to m_foo:

// int *MyClass::m_foo;
void MyClass::refresh_foo(int x) {
    delete m_foo;
    m_foo = new int(x * 3 + 5);
}

From the Compiler Explorer, gcc, clang, and MSVC all generate less code for the old way than the new one. I understand why this is the case, since that’s the order in which all expressions are evaluated; p = q; has to construct q first. And of course m_foo had an invalid value in between the delete and new lines. But is there a way I’m missing to have unique_ptr destroy its old value and then create a new one in one expression? A “replace_unique“? Seems like it would be helpful when dealing with large objects so two of them don’t needlessly coexist.

Edit: To be clear, I’m just using int as a trivial example here. My actual use cases are with classes of my own or from a library. And m_foo.reset(new int(x * 3 + 5)); naturally has the same problem compared to the old way of doing things, since it too has to construct the new int before assigning it and deleting the previous one.

Answer

You can use unique_ptr::reset() to deterministically destroy the currently held object when you want. Update the unique_ptr with a nullptr pointer before then updating it with a new object pointer, eg:

// std::unique_ptr<int> MyClass::m_foo;
void MyClass::refresh_foo(int x) {
    m_foo.reset(); // <- int is destroyed here
    m_foo = std::make_unique<int>(x * 3 + 5);
}