jotik
jotik

Reputation: 17920

What is the order of destruction of function arguments?

If some function f with parameters p_1, ..., p_n of types T_1, ..., T_n respectively is called with arguments a_1, ..., a_n and its body throws an exception, finishes or returns, in what order are the arguments destroyed and why? Please provide a reference to the standard, if possible.

EDIT: I actually wanted to ask about function "parameters", but as T.C. and Columbo managed to clear my confusion, I'm leaving this question be about the arguments and asked a new separate question about the parameters. See the comments on this question for the distinction.

Upvotes: 36

Views: 3079

Answers (3)

R Sahu
R Sahu

Reputation: 206697

The order in which the arguments to a function are evaluated is not specified by the standard. From the C++11 Standard (online draft):

5.2.2 Function call

8 [ Note: The evaluations of the postfix expression and of the argument expressions are all unsequenced relative to one another. All side effects of argument expression evaluations are sequenced before the function is entered (see 1.9). —end note ]

Hence, it is entirely up to an implementation to decide in what order to evaluate the arguments to a function. This, in turn, implies that the order of construction of the arguments is also implementation dependent.

A sensible implementation would destroy the objects in the reverse order of their construction.

Upvotes: 12

6502
6502

Reputation: 114569

In §5.2.2[4] N3337 is quite explicit on what happens (online draft):

During the initialization of a parameter, an implementation may avoid the construction of extra temporaries by combining the conversions on the associated argument and/or the construction of temporaries with the initialization of the parameter (see 12.2). The lifetime of a parameter ends when the function in which it is defined returns.

So for example in

f(g(h()));

the return value from the call h() is a temporary that will be destroyed at the end of the full expression. However the compiler is allowed to avoid this temporary and directly initialize with its value the parameter of g(). In this case the return value will be destroyed once g() returns (i.e. BEFORE calling f()).

If I understood correctly what is stated in the standard however it's not permitted to have the value returned from h() to survive to the end of the full expression unless a copy is made (the parameter) and this copy is destroyed once g() returns.

The two scenarios are:

  1. h return value is used to directly initialize g parameter. This object is destroyed when g returns and before calling f.
  2. h return value is a temporary. A copy is made to initialize g parameter and it is destroyed when g returns. The original temporary is destroyed at the end of the full expression instead.

I don't know if implementations are following the rules on this.

Upvotes: 14

Zereges
Zereges

Reputation: 5209

I did not manage to find the answer in the standard, but I was able to test this on 3 most popular C++ compliant compilers. The answer of R Sahu pretty much explains that it is implementation defined.

§5.2.2/8: The evaluations of the postfix expression and of the arguments are all unsequenced relative to one another. All side effects of argument evaluations are sequenced before the function is entered.

Visual Studio C++ Compiler (Windows) and gcc (Debian)
Arguments are constructed in order reverse to their declaration and destroyed in reversed order (thus destroyed in order of delcaration):

2
1
-1
-2

Clang (FreeBSD)
Arguments are constructed in order of their declaration and destroyed in reversed order:

1
2
-2
-1

All compilers were instructed to treat the source code as C++11 and I used the following snippet to demonstrate the situation:

struct A
{
    A(int) { std::cout << "1" << std::endl; }
    ~A() { std::cout << "-1" << std::endl; }
};

struct B
{
    B(double) { std::cout << "2" << std::endl; }
    ~B() { std::cout << "-2" << std::endl; }
};

void f(A, B) { }

int main()
{
    f(4, 5.);
}

Upvotes: 22

Related Questions