C++ object return
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 sho开发者_JS百科uld always implement rule of three to ensure consistent behaviour?
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.
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
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.
getObject() would return a copy of a, and the original object created in getObject is destroyed on exiting the function, but there can be Return Value Optimization (depends on the compiler you're using).
Besides the mismatched return types in the example, you are probably looking for return value optimization, or more general, copy elision. If I remember correctly, the copy elision rules are even specified in the C++ standard, although somewhat vague.
Is the memory that the object took up in the function call simply deleted without running the destructor?
No. With optimizations disabled, the local object will be destructed (and the destructor invoked). If a copy-elision optimization takes place, the local object will really just be a "reference" (note the quotes) for the one in main - in that case the destructor will not be run within the function, but the memory will not be de-allocated either.
In getObject, you are creating TestObject on the stack, so the return value is invalid. To create an object on the heap, use "new". I don't believe the destructor is called when the method's scope is exited, I think the memory on the stack is simply reclaimed.
精彩评论