Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Return Value Optimization - C++ - Destructor calls

Tags:

c++

rvo

nrvo

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.

like image 441
Venky Avatar asked Feb 12 '12 10:02

Venky


People also ask

Does C have return value optimization?

> Note also that C doesn't have return-value-optimization, hence all your struct-returning functions will cause a call to memcpy (won't happen when compiled in C++ mode of course).

Is destructor called after return?

While returning from a function, destructor is the last method to be executed. The destructor for the object “ob” is called after the value of i is copied to the return value of the function. So, before destructor could change the value of i to 10, the current value of i gets copied & hence the output is i = 3.

Does destructor return a value?

Declaring destructorsDo not return a value (or void ). Cannot be declared as const , volatile , or static . However, they can be invoked for the destruction of objects declared as const , volatile , or static .

Can a deconstructor return a value?

If you didn't author a class, struct, or interface, you can still deconstruct objects of that type by implementing one or more Deconstruct extension methods to return the values in which you're interested.


2 Answers

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.

like image 150
Nawaz Avatar answered Sep 18 '22 02:09

Nawaz


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.

like image 25
LihO Avatar answered Sep 21 '22 02:09

LihO