Alex Alex - 3 months ago 7
C++ Question

Does standard C++11 guarantee that temporary object passed to a function will have been deleted after the end of the function?

As known, that standard C++11 guarantees that temporary object passed to a function will have been created before function call: Does standard C++11 guarantee that temporary object passed to a function will have been created before function call?

But, does standard C++11 guarantee that temporary object passed to a function will have been deleted after the end of the function (not before)?

Working Draft, Standard for Programming Language C++ 2016-07-12: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/n4606.pdf


§ 12.2 Temporary objects

§ 12.2 / 5

There are three contexts in which temporaries are destroyed at a
different point than the end of the full expression.
The first context
is when a default constructor is called to initialize an element of an
array with no corresponding initializer (8.6). The second context is
when a copy constructor is called to copy an element of an array while
the entire array is copied (5.1.5, 12.8). In either case, if the
constructor has one or more default arguments, the destruction of
every temporary created in a default argument is sequenced before the
construction of the next array element, if any. The third context is
when a reference is bound to a temporary.


Also:


§ 1.9 / 10

A full-expression is an expression that is not a subexpression of
another expression. [ Note: in some contexts, such as unevaluated
operands, a syntactic subexpression is considered a full-expression
(Clause 5). — end note ] If a language construct is defined to produce
an implicit call of a function, a use of the language construct is
considered to be an expression for the purposes of this definition. A
call to a destructor generated at the end of the lifetime of an object
other than a temporary object is an implicit full-expression.
Conversions applied to the result of an expression in order to satisfy
the requirements of the language construct in which the expression
appears are also considered to be part of the full-expression.


Does it mean that standard C++11 guarantees that temporary object passed to a function will have been deleted not before the function will end - and exactly at the end of the full expression?

http://ideone.com/GbEPaK

#include <iostream>
using namespace std;

struct T {
T() { std::cout << "T created \n"; }
int val = 0;
~T() { std::cout << "T destroyed \n"; }
};

void function(T t_obj, T &&t, int &&val) {
std::cout << "func-start \n";
std::cout << t_obj.val << ", " << t.val << ", " << val << std::endl;
std::cout << "func-end \n";
}

int main() {

function(T(), T(), T().val);

return 0;
}


Output:

T created
T created
T created
func-start
0, 0, 0
func-end
T destroyed
T destroyed
T destroyed


Can we say that the
T destroyed
will always be after the
func-end
?

And this:

function(T(), T(), T().val);


Is always equal to this:

{
T tmp1; T tmp2; T tmp3;
function(tmp1, tmp2, tmp3.val);
}

Answer

Well, you already quoted all the text that tells us the temporary's lifetime ends at the end of the full-expression. So, yes, "T destroyed" will always come last.

If the destruction had no observable side-effects then, per the as-if rule, it could actually happen at any time afterwards… but that's moot because, well, it wouldn't be observable.

However, the final two snippets you presented are not generally equivalent, because you fixed the order of construction/initialisation in a way that it wasn't before. Function arguments have an unspecified evaluation order. Again, though, for this particular T the difference is not observable.