I know that NRVO allows a function to build an object and return that object at a cost without the cost of copying or even a move operation. He found that it also works with nested function calls, which allows you to build an object from the return value of another function call.
Please consider the following program and output it as shown in the comments:
(Output from Visual Studio 2017, version 15.2, build release.)
#include <stdio.h>
class W
{
public:
W() { printf( "W::W()\n" ); }
W( const W& ) { printf( "W::W( const W& )\n" ); }
W( W&& ) { printf( "W::W( W&& )\n" ); }
W& operator=( const W& ) { printf( "W::operator=( const W& )\n" ); }
W& operator=( W&& ) { printf( "W::operator=( W&& )\n" ); }
~W() { printf( "W::~W()\n" ); }
void Transform() { printf( "W::Transform()\n" ); }
void Run() { printf( "W::Run()\n" ); }
};
W make()
{
W w;
return w;
}
W transform_make()
{
W w{ make() };
w.Transform();
return w;
}
W transform1( W w )
{
w.Transform();
return w;
}
W&& transform2( W&& w )
{
w.Transform();
return std::move(w);
}
int main()
{
printf( "TestM:\n" );
{
W w{ make() };
w.Run();
}
printf( "TestTM:\n" );
{
W w{ transform_make() };
w.Run();
}
printf( "TestT1:\n" );
{
W w{ transform1( make() ) };
w.Run();
}
printf( "TestT2:\n" );
{
W&& w{ transform2( make() ) };
w.Run();
}
}
TestMis a normal case of NRVO. An object Wis created and destroyed only once.
TestTMis an embedded case of NRVO. Again, an object is built only once and is never copied or moved. So far so good.
- TestT1 , TestTM? TestT1, - . transform1(), - ? , TestT1 TestTM, , , .
, TestT2, RValue. , , , , , .
Update:
, , :
W&& transform2( W&& w )
{
w.Transform();
return std::move(w);
}
void run( W&& w )
{
w.Run();
}
printf( "TestT3:\n" );
{
run( transform2( make() ) );
}
?