http://en.wikipedia.org/wiki/Return_value_optimization
http://msdn.microsoft.com/en-us/library/ms364057(VS.80).aspx
simple example
A MyMethod (B &var) { A retVal; retVal.member = var.value + bar(var); return retVal; }
valA = MyMethod(valB);
Hidden argument code without NRVO (pseudo code)
A MyMethod (A &_hiddenArg, B &var) { A retVal; retVal.A::A(); // constructor for retVal retVal.member = var.value + bar(var); _hiddenArg.A::A(retVal); // the copy constructor for A return; retVal.A::~A(); // destructor for retVal }
Hidden argument code with NRVO (pseudo code)
A MyMethod(A &_hiddenArg, B &var)
{
_hiddenArg.A::A();
_hiddenArg.member = var.value + bar(var);
Return
}
Code Samples
Sample 1: Simple example
#include <stdio.h>
class RVO
{
public:
RVO()
{
printf("I am in constructor %d\n", this);
}
RVO (const RVO& c_RVO)
{
printf ("I am in copy constructor %d\n", this);
}
~RVO()
{
printf ("I am in destructor %d\n", this);
}
RVO& operator=(const RVO& rhs)
{
printf ("I am in operator %d = %d\n", this, &rhs);
return *this;
}
int mem_var;
};
RVO MyMethod (int i)
{
printf("3\n");
RVO rvo; //I am in constructor 1244896
printf("4\n");
rvo.mem_var = i;
printf("5\n");
return (rvo); //1244948CC, ~1244896
printf("6\n");
}
int main()
{
printf("1\n");
RVO rvo; //I am in constructor 1245016
printf("2\n");
rvo=MyMethod(5); //I am in copy constructor
printf("7\n");
return 0; //~1245016
}
Figure 4. Sample1.cpp
Compiling sample1.cpp with and without NRVO turned on will yield different behavior.
Without NRVO (cl /Od sample1.cpp), the expected output would be:
1
I am in constructor 1245016
2
3
I am in constructor 1244888
4
5
I am in copy constructor 1244944
I am in destructor 1244888
I am in operator 1245016 = 1244944
I am in destructor 1244944
7
I am in destructor 1245016
With NRVO (cl /O2 sample1.cpp), the expected output would be:
1
I am in constructor 1245048
2
3
I am in constructor 1245052
4
5
I am in operator 1245048 = 1245052
I am in destructor 1245052
7
I am in destructor 1245048