What is the order of calling destructors for temporaries in C++?

c++, destructor, object-lifetime, temporary

Solution

Let's talk about subexpressions and their sequencing. If `E1` is sequenced before `E2`, that means `E1` must be fully evaluated before `E2` is. If `E1` is unsequenced with `E2`, that means `E1` and `E2` may be evaluated in any order.

For `f(A()) << B()`, which is in your case the same as `f(A()).operator<<(B())`, we know that:

- `A()` is sequenced before `f(...)`,

- `f(...)` is sequenced before `operator<<` and

- `B()` is sequenced before `operator<<`

This also tells us that:

- `A()` is sequenced before `operator<<`

- `A()` is unsequenced with `B()`

- `f(...)` is unsequenced with `B()`

If we assume RVO, so as not to complicate things, the possible order a compiler could evaluate the subexpressions in are:

- `A()` -> `f(...)` -> `B()`, yielding `~B()` -> `~C()` -> `~A()`

- `A()` -> `B()` -> `f(...)`, yielding `~C()` -> `~B()` -> `~A()`

- `B()` -> `A()` -> `f(...)`, yielding `~C()` -> `~A()` -> `~B()`

The latter is the order observed in the OP. Note that the order of destruction is always the reverse order of construction.

Problem

Consider the following code: ``` #include <iostream> struct A { ~A() { std::cout << "~A" << std::endl; } }; struct B { ~B() { std::cout << "~B" << std::endl; } }; struct C { ~C() { std::cout << "~C" << std::endl; } void operator<<(const B &) {} }; C f(const A &a = A()) { return C(); } int main() { f(A()) << B(); } ``` Compiling with GCC and running gives the following output: ``` ~C ~A ~B ``` Is it guaranteed that the destructors for temporary objects of types A, B and C will be called in this order when compiled with other compilers? In general, what is the order of destructor calls for temporaries if there is any?

Original source