C++ temporary objects lifetime in a function call
Asked Answered
G

3

6

When we pass an object which is managed by temporary smart pointer to a function by raw pointer or by reference, does the standard guarantee that the object's lifetime will extend to the function lifetime?

#include <iostream>
#include <memory>

struct A {
  ~A() {
    std::cout << "~A()" << std::endl;
  }
};

std::unique_ptr<A> makeA() {
  return std::make_unique<A>();
}

void f(const A& a) {
  std::cout << "f()" << std::endl;
}

int main() {
  f(*makeA());
  return 0;
}

I would expect that the instance of A managed by unique_ptr is destroyed once the raw pointer is obtained from it, as it is a temporary and it is not bound to function arguments. So the output could be

~A()
f()

But both gcc and clang make it live till the function ends, i.e. the output is

f()
~A()

So it seems that the temporary smart pointer is not destroyed.

Why does the A instance (located in the heap) live till the function end? Some reference to the standard is highly appreciated.

Garibaldi answered 4/9, 2019 at 7:26 Comment(2)
Where do you believe a raw pointer is "obtained"?Lugubrious
I would recommend adding the language-lawyer tag if you would like answers to support their assertions with quotes from the standard. (I would not add it now since multiple answers have already been posted, but your future questions might benefit from it).Salomie
A
9

Temporaries live until the end of the full-expression in which they were created (with some life time extension exceptions), see [class.temporary]/4.

In your case the temporary of interest of type std::unique_ptr<A> is created by makeA() and the full-expression this is a subexpression of is f(*makeA());, so the temporary's life time will end at that semicolon.

The object that the unique_ptr manages is also destroyed only when the unique_ptr itself is destroyed (that is the purpose of the smart pointer).

For exceptions to that rule, see the following paragraph of the standard.

Annmarie answered 4/9, 2019 at 7:29 Comment(0)
C
5

From the standard, [class.temporary]/4

(emphasis mine)

Temporary objects are destroyed as the last step in evaluating the full-expression ([intro.execution]) that (lexically) contains the point where they were created. This is true even if that evaluation ends in throwing an exception. The value computations and side effects of destroying a temporary object are associated only with the full-expression, not with any specific subexpression.

That means, it has nothing to do with the temporary being bound to the function parameter, the temporary constructed by makeA() won't be destroyed until the full-expression ends, which includes the invocation of the function f.

Cufic answered 4/9, 2019 at 7:38 Comment(0)
E
3

*makeA() is dereferencing the anonymous temporary created by the call to makeA.

The standard guarantees that the anonymous temporary survives the function call - in other words ~A is called conceptually when program control reaches the end of the statement.

Eisegesis answered 4/9, 2019 at 7:30 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.