Reputation: 71
The following code calls the destructor 4 times:
#include<iostream>
using namespace std;
class A{
public:
A(){cout<<"A"<<endl;}
~A(){cout<<"~A"<<endl;}
A f(){cout<<"F"<<endl; A b; return b;}
};
int main(){
A a,b;
b=a.f();
}
OUTPUT:
A
A
F
A
~A
~A
~A
~A
Can some one please explain? I was thinking that there should be only three destructor calls.
Upvotes: 5
Views: 2181
Reputation: 42083
There are 2 objects in main: A a,b;
, one object in the body of function f()
: A b;
and then there is temporary object that is being copied and its copy stored into b
.
When returning b
in the body of your function, copy is created at first, then the local b
is destructed, then copy is assigned into variable b
declared in main and then this copy is destructed.
Add following line to class A
definition and see yourself:
A(const A&) { cout << "copying" << endl; }
With Named Return Value Optimization, the compiler tries to eliminate redundant Copy constructor and Destructor calls which means that local b
from the function f()
will be assigned into variable b
in main without copy being created. So with RVO / NRVO only 3 objects are created in your case.
Although there is a way how to avoid destructing this copy without RVO in your case:
A a;
A b = a.f();
in this case copy of return value of function f()
is created and stored as a variable b
. Which also means that no assigment operator is called and only 2 objects are created in main: a
and copy of b
returned by f()
.
Hope this helps.
Upvotes: 3
Reputation: 8004
Local variable in f
is copied into a temporary variable when the function returns. That is why there are four destructor calls. (Copy operation calls the copy constructor A(A&)
not your default constructor A()
, hence three A
s.)
Upvotes: 0
Reputation: 9526
There is one hidden creation and destruction of an instance of A
: when you're returning from function f()
, a temporary copy of object b
is created. It's assigned to b
in main()
and then destroyed.
Upvotes: 1
Reputation: 258568
You can't rely on RVO to occur. That's why you should never put functional logic inside destructors or copy constructors (yes, those too can be elided).
Return value optimization is just something the standard allows, but does not enforce.
With no optimization or O2, I too get 4 destructor callse.
With full optimization - Ox - I only get 3.
Upvotes: 0
Reputation: 361322
There are two objects in main()
, so the destructor will be called two times just because of them. One object in f()
, so the destructor will be called one time just because of it. Total 3 times (which you expect, but read on...)
Now the fourth time destructor is called for the temporary object which is created when returning from f
. This can happen only when there is no RVO at all. RVO is compiler's choice which means it may optimize it, or it may not. The language doesn't give any guarantee of RVO.
Anyway, just increase your optimization level; I'm sure you will see at most 3 destructor invocations only.
Upvotes: 8
Reputation: 96258
Your compiler didn't optimize it. Have you compiled it with optimizations enabled?
Here is the output of the same code, compiled with gcc:
A
A
F
A
~A
~A
~A
Upvotes: 1