Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does standard C++11 guarantee that temporary object passed to a function will have been destroyed 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 destroyed 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 destroyed 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);
}
like image 269
Alex Avatar asked Aug 15 '16 11:08

Alex


1 Answers

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.

like image 101
Lightness Races in Orbit Avatar answered Sep 30 '22 15:09

Lightness Races in Orbit