I want to implement a construction which is more efficient when returning big structures by value, using an unnamed temporary ('prvalue') as an default formal parameter. First I'll show an example of the performance problem which it will solve:
If we have a structure:
struct BIG_STRUCT
{
char aArray[260];
char aArray1[260];
} ;
And a function that initialize a temporary of it and then return it by value like this:
BIG_STRUCT Func()
{
BIG_STRUCT sTemp;
/*init sTemp*/
return sTemp; // or BIG_STRUCT(sTemp) // constructs the return value by using a temporary
}
I believe now you saw where the performance issue is - 2 copies of BIG_STRUCT are created on the stack - 1 for the temporary used to 'construct' the return value and 1 for the return value itself. Also at the return statement a 'copy constructor' is called to initialize the return value using the temporary. So both memory and execution time are wasted. Now you maybe think why not return by reference? But this will result in a dangling reference as function temporaries are 'destructed' at the end of the function scope they belong to (it wouldn't work even it the reference is 'rvalue' one). Example:
BIG_STRUCT & /* or 'rvalue' one - '&&' */ Func()
{
BIG_STRUCT sTemp;
/*init sTemp*/
return sTemp; // return a local by reference - resulting in dangling reference
}
The solution of this problem as I said at the beginning by creating the return value temporary ourselves at the function call, using an unnamed variable as a default formal parameter with type 'rvalue' reference and returning again an 'rvalue' reference to this object. So the optimized version of 'BIG_STRUCT Func()' will looks like this:
BIG_STRUCT &&Func(BIG_STRUCT &&result = BIG_STRUCT())
{
//BIG_STRUCT sTemp;
/*init result*/
return (BIG_STRUCT&&)result; //converts 'lvavlue' to 'xvalue'
}
This will work the same way as if the function is actually returning a value but without the performance issues. There is only one problem with this construction which is that the function returns an 'rvalue' reference so if we assign it's return value to 'rvalue' reference it's life-time wouldn't be extended and this will result in a dangling reference. What I mean is that the new standard allow us to extend 'prvalues' life-time by assigning them to an 'rvalue' reference. But we are not returning one in the current example, so code like this will be invalid:
BIG_STRUCT && refPrvalue = Func();
refPrvalue.aArray[3] = 0; //unknown result accessing dangling reference
Any solution how can I fix this problem?