The behavior of this program is actually undefined, the identifier __
is reserved and we can see from the draft C++ standard 17.6.4.3
Reserved names paragraph 2 says:
If a program declares or defines a name in a context where it is reserved, other than as explicitly allowed by this Clause, its behavior is undefined.
and if we look further to section 17.6.4.3.2
Global names which says:
Each name that contains a double underscore _ _ or begins with an underscore followed by an uppercase letter (2.12) is reserved to the implementation for any use.
so unless the compiler documents that __
is free to be used by user code then it is reserved.
Destructors are invoked implicitly
So if this program did not invoke undefined behavior the rules for destructors that are invoked implicitly can be taken from the draft standard section 12.4
Destructotrs paragraph 11 which says (emphasis mine)
— for constructed objects with static storage duration (3.7.1) at program termination (3.6.3),
— for constructed objects with thread storage duration (3.7.2) at thread exit,
— for constructed objects with automatic storage duration (3.7.3) when the block in which an object is created exits (6.7),
— for constructed temporary objects when the lifetime of a temporary object ends (12.2),
so that means the destructor for an automatic object will be invoked when you exit work()
, which has to happen after the results are returned. We can see further that the order of objects are destroyed in is also specified from 6.6
Jump statements:
On exit from a scope (however accomplished), objects with automatic storage duration (3.7.3) that have been constructed in that scope are destroyed in the reverse order of their construction. [ Note: For temporaries, see 12.2. —end note ]
Note that names that contain a double underscore __
, or start with either an underscore followed by an uppercase letter are reserved in any scope.