Is there any definition of the order of destruction of objects returned from a method that can be put into a structured binding statement? cppreference doesn't seem to mention destruction order, and a quick test on godbolt reveals something other than what I expected.
#include <iostream>
#include <tuple>
struct A{
A()=default;
~A(){ std::cout << "~A()" << std::endl; }
};
struct B{
B()=default;
~B(){ std::cout << "~B()" << std::endl; }
};
struct C{
C()=default;
~C(){ std::cout << "~C()" << std::endl; }
};
auto MakeStuff()
{
auto a = A{};
auto b = B{};
auto c = C{};
return std::make_tuple(std::move(c), std::move(b), std::move(a));
}
int main()
{
auto&& [c, b, a] = MakeStuff();
std::cout << "Results now: " << std::endl;
}
Results:
Program returned: 0
~C()
~B()
~A()
Results now:
~C()
~B()
~A()
I guess structured binding constructs the objects in the [brackets] from right to left, seeing as how the destructors invoked as c
first, then b
, then a
. Is this standard behavior, or am I relying on something implementation-specific here?
Thank you.
CodePudding user response:
Structured binding changes absolutely nothing about the language in terms of order of construction/destruction. Structured binding is a fiction, a linguistic shorthand that turns get<I>(unnamed_object)
or unnamed_object.some_name
into some_name
. In this fiction, unnamed_object
is the actual object which is generated by the expression and captured by the auto[]
structured binding declaration.
That object works exactly like any other C object. The order of subobject declarations in the class (if it is a class) determines the order of construction and destruction, just like any other C object.
Now, when it comes to std::tuple
, the order of its subobject declaration is unspecified; it is allowed to vary from implementation to implementation. Again, structured binding has nothing to do with that. So the order of destruction can be whatever your particular implementation wants it to be.