2

If I have a function source that returns a unique_ptr, and I have a function sink that calls source in the following way, it works [clang].

But is the behavior undefined? Or is everything copacetic?

class Foo {
  ...
  bool isValid() { return true; }
  ...
}

std::unique_ptr<Foo> source() {
  auto foo = std::make_unique<Foo>();  // let's pretend this is C++14?
  /* ... initialize foo */
  return foo;
}

void sink() {
  if (source()->isValid()) {
    /* do something */
  }
  /* ... */
}

Is it valid to use the unique_ptr on that line only? And when is the object theoretically supposed to be destructed? After that line? At the end of the function?

Praetorian
  • 100,267
  • 15
  • 224
  • 307
wrhall
  • 1,228
  • 1
  • 11
  • 25

2 Answers2

4

Yes, your code is valid. The unnamed temporary unique_ptr returned by source will be destroyed at the end of the full expression in which it was created, in this case the condition within the if statement.

From N3337, §12.2/3 [class.temporary]

... Temporary objects are destroyed as the last step in evaluating the full-expression (1.9) that (lexically) contains the point where they were created. ...

And from §6.4/1 [stmt.select], the grammar for an if statement is

Selection statements choose one of several flows of control.

  selection-statement:
      if ( condition ) statement
      ...
  condition:
      expression
      ...

Note that return std::move(foo); is not necessary, you can write return foo; and the unique_ptr will be automatically moved.

Praetorian
  • 100,267
  • 15
  • 224
  • 307
3

The result of calling a function that returns an object (and not a(n lvalue) reference) is a temporary, therefore it's alive until the end of the full expression, which is the whole condition of the if statement in this case. Hence the code is valid.