Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ object return

Tags:

c++

TestObject getObject(){
    TestObject a(5.0f);
    return a;
}

int main(){
    TestObject a = getObject();
}

Am I right in saying that in C++ a returned object will not have it's destructor called as it is returned. Is the memory that the object took up in the function call simply deleted without running the destructor?

Ok a specific example..

#include <iostream>

class Test{
public:
 Test(){};
 ~Test(){std::cout << "Goodbye cruel world\n";}
};


Test getAnObject(){
 Test a;
 return a;
}

int main(){
 Test a = getAnObject();
}

If I run this the destructor is run just once (not for the local object in getAnObject()). Can I assume this will always be the case?

#include <iostream>

class Test{
public:
 Test(){};
 ~Test(){std::cout << "Goodbye cruel world\n";}
};


Test getAnObject(){
 Test a;
 Test b;
 int i = 0;
 if (i){
  return a;
 }else{
  return b;
 }
}

int main(){
 Test a = getAnObject();
}

Following the RVO guide this test has the destructor run on both objects in getanobject() and in the main function. Is this a case where I should always implement rule of three to ensure consistent behaviour?

like image 261
Guest300000000 Avatar asked Dec 09 '10 15:12

Guest300000000


3 Answers

If I run this the destructor is run just once (not for the local object in getAnObject()). Can I assume this will always be the case?

For correctness? No. For efficiency? Yes. -ish.

To elaborate: strictly speaking, the local object will be copied when returning from the function. The local storage will then be cleaned up by calling the local object’s destructor.

However, the compiler is free to generate different code that yields the same observable behaviour. In particular, the standard grants the compilers the right to elide the copying of the return value, and reuse the same storage location for both objects (the local object and the receiving object of the return value). In doing so, the compiler might not need to call the copy constructor, nor the destructor (since it’s reusing the same memory location).

However, this optimization (called “named return value optimization”, NRVO) is not guaranteed by the standard (and in fact it’s not possible to perform everywhere). You cannot assume that it will happen for correctness. In particular, your object still needs a well-defined copy constructor and destructor, otherwise the program is ill-formed.

On the other hand, you can reasonably expect all modern compilers to perform this optimization where ever it is possible. You can therefore (usually) rely on this optimization from a performance point of view.

like image 90
Konrad Rudolph Avatar answered Nov 16 '22 08:11

Konrad Rudolph


It is implementation based. It is knows as Return Value Optimization technique. Check this out for more info:

http://en.wikipedia.org/wiki/Return_value_optimization

like image 40
LavaScornedOven Avatar answered Nov 16 '22 08:11

LavaScornedOven


getObject() would return a copy of a. Here is what happens if the compiler does not do any optimization. A temporary copy of a will be created using the copy constructor of TestObject. Then the original a will be destroyed, and its destructor will be called, and then the temporary object will be copied into the local variable a in the main() function. The temporary will then also be destroyed, and its destructor will be called.

Since the return value of getObject() is immediately assigned to a variable in this particular case, a modern compiler will probably be able to optimize away at least one of the copy operations.

like image 3
Dima Avatar answered Nov 16 '22 09:11

Dima