This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 119a. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.
2025-12-20
[Voted into the WP at the March, 2009 meeting.]
In describing the order of destruction of temporaries,6.8.7 [class.temporary] paragraphs 4-5 say,
There are two contexts in which temporaries are destroyed at adifferent point than the end of the full-expression...
The second context is when a reference is bound to atemporary... A temporary bound to the returned value in a functionreturn statement (8.8.4 [stmt.return]) persists until thefunction exits.
The following example illustrates the issues here:
struct S { ~S(); }; S& f() { S s; // #1 return (S(), // #2 S()); // #3 }If the return type off() were simplyS insteadofS&, the two temporaries would be destroyed at the endof the full-expression in thereturn statement in reverseorder of their construction, followed by the destruction of thevariables at block-exit, i.e., the order of destructionof theS objects would be #3, #2, #1.
Because the temporary #3 is bound to the returned value, however,its lifetime is extended beyond the end of the full-expression, sothatS object #2 is destroyed before #3.
There are two problems here. First, it is not clear what“until the function exits” means. Does it mean thatthe temporary is destroyed as part of the normal block-exitdestructions, as described in 8.8 [stmt.jump] paragraph 2:
On exit from a scope (however accomplished), destructors (11.4.7 [class.dtor]) are called for all constructed objects with automaticstorage duration (6.8.6.4 [basic.stc.auto]) (named objects ortemporaries) that are declared in that scope, in the reverse order oftheir declaration.
Or is the point of destruction for #3after the destruction of the “constructed objects...that aredeclared [emphasis mine] in that scope”(because temporary #3 was not “declared”)? I.e.,should #3 be destroyed before or after #1?
The other problem is that, according to the recollection of oneof the participants responsible for this wording, the intent was notto extend the lifetime of #3 but simply to emphasize that itslifetime ended before the function returned, i.e., that the result off() could not be used without causing undefined behavior.This is also consistent with the treatment of this example by manyimplementations; MSVC++, g++, and EDG all destroy #3 before #2.
Suggested resolution:
Change 6.8.7 [class.temporary] paragraph 5 as indicated:
AThe lifetime of a temporary bound to the returnedvalue in a function return statement (8.8.4 [stmt.return])persists until the function exitsis not extended; it isdestroyed at the end of the full-expression in the return statement.
Proposed resolution (June, 2008):
Change 6.8.7 [class.temporary] paragraph 5 as follows (convertingthe running text into a bulleted list and making the indicated editsto the wording):
... The temporary to which the reference is bound or the temporarythat is the complete object of a subobject to which the reference isbound persists for the lifetime of the reference except:asspecified below.
A temporary bound to a reference member in a constructor'sctor-initializer (11.9.3 [class.base.init]) persists until theconstructor exits.
A temporary bound to a reference parameter in a function call(7.6.1.3 [expr.call]) persists until the completion of the fullexpression containing the call.
AThe lifetime of a temporary bound to thereturned value in a function return statement (8.8.4 [stmt.return])persists until the function exitsis not extended; thetemporary is destroyed at the end of the full-expression in the returnstatement.The destruction of a temporary whose lifetime is not extended...