1

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;
}
AustinWBryan
  • 3,249
  • 3
  • 24
  • 42
kfmfe04
  • 14,936
  • 14
  • 74
  • 140

2 Answers2

5

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;
kennytm
  • 510,854
  • 105
  • 1,084
  • 1,005
1

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
}
hpsMouse
  • 2,004
  • 15
  • 20
  • 3
    @kfmfe04 I don't think `std::move()` is a good idea in this case. According to [Move Semantics and Compiler Optimizations](http://thbecker.net/articles/rvalue_references/section_06.html) it makes things worse. – Ali Dec 08 '12 at 10:33
  • If you are looking for optimization, (N)RVO is *more* optimal than move constructors. A move operation into a constructor is still a shallow copy -- it's better than a deep copy but worse than no copy at all. – Mark Lakata Apr 08 '15 at 02:17
  • @MarkLakata You are right. `std::move` shouldn't be used to return a named automatic object. I have edited my answer. – hpsMouse May 22 '15 at 15:27