Recently I read a book talking about the c++11, which described a very interesting thing. The RVO/NRVO of compiler.
What is RVO
The Wikipedia has a very clearly explanation.
In the context of the C++ programming language, the return value optimization (RVO) is a compiler optimization that involves eliminating the temporary object created to hold a function's return value.
Write some code
class A {
public:
A() {
cout << "Default constructor!" << endl;
}
A(const A& other) {
cout << "Copy contructor!" << endl;
}
};
A getA() {
return A();
}
int main() {
A b = getA();
return 0;
}
At last we found that the copy constructor was not called. Only the default constructor was called. That is to say, the compiler just initialized one instance of A in this program. The return value from the function getA() will have same memory address with the variable b.
Default constructor!
One more interesting thing is that we can let the compiler not to do this optimization. When we compile the code with gcc/g++, we can append this flag -fno-elide-constructors
to gcc/g++ to turn off RVO.
Then we try to run the code described before with this flag. The copy constructor is called twice.
Default constructor!
Copy contructor!
Copy contructor!
If we turn off this optimization, there is a hidden temporary object, the compiler will first copy the return value to a temporary variable, then copy the temporary variable to the variable which will be assigned from the method return value.
tmp = a; // one copy
b = tmp; // another copy
About NRVO
As @tamy0612 described bellow, my old version code is a NRVO. If we return a named object inside the function. This may be optimized by the NRVO if the compiler supports NRVO. Also we can turn off the NRVO by using the flag -fno-elide-constructors
.
A getA() {
A a;
printf("Address of a: %p\n", &a);
return a;
}
int main() {
A b = getA();
printf("Address of b: %p\n", &b);
return 0;
}
With NRVO
Default constructor!
Address of a: 0x7fff583c35a8
Address of b: 0x7fff583c35a8
Turn off NRVO with -fno-elide-constructors
Default constructor!
Address of a: 0x7fff52ebb578
Copy contructor!
Copy contructor!
Address of b: 0x7fff52ebb5a8