Question

This is a question about C++ specs on object destruction vs Return-Value-Optimization.

Can I expect RVO return the right value before std::unique_ptr<> cleanup?

Foo
Bar()
{
  std::unique_ptr<Foo> ptr = new Foo;
  return *ptr;
}
Was it helpful?

Solution

It will return the right value with or without RVO (and there is no RVO in this case). The function returns a concrete Foo, so *ptr will be copied into the return value before destruction of the pointer.

That means,

Foo foo;
foo = Bar();

is similar to (unwrapping the unique_ptr to be more explicit)

  Foo foo;
  Foo* ptr = new Foo;
  foo = *ptr;
finally:
  delete ptr;

OTHER TIPS

When a function returns a class type object, RVO is allowed under only two circumstances:

  • The returned expression is the name of a non-volatile automatic object, or
  • the returned expression refers to a temporary object which has not been bounded to a reference.

So your code won't trigger RVO.

If the Foo object is declared with automatic storage, a compiler is allowed to do RVO:

Foo bar()
{
    Foo foo;
    return foo;    // foo can be constructed directly as the returned object
}

If for some reason you have to create the object with new and want to eliminate the copy operation, you may use std::move, which will change an expression into an rvalue:

Foo bar()
{
    std::unique_ptr<Foo> ptr(new Foo);
    return std::move(*ptr);    // No deep copy if Foo implements
                               // its own move constructor
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top