Re: Is std::move going to be at least as fast as RVO?
DeMarcus <use_my_alias_here@hotmail.com> writes:
Hi,
Let's say I have this function.
std::vector<std::string> fnc()
{
std::vector<std::string> vec;
while( youDontWantToWaitThisLong() )
{
vec.push_back( getSomeData() );
}
return vec;
}
As I understand, the use of rvalue references and the movement of data
will take effect when I do one single change to the above function:
return std::move( vec );
And moreover, as I understand, this will also compile even though the
return value is of a type that has not implemented the move constructor
MyClass( MyClass&& );
Therefore, it would be natural to just put std::move everywhere a
function returns by value (and the data needs no copy).
Now, am I guaranteed that std::move will be as efficient as RVO when the
returned type has implemented the move constructor?
What are the guidelines using std::move? Shall I start put it everywhere
I return by value?
As I understand it I believe that you will not be doing yourself any
favours here and may actually be introducing *extra* copying for the
case where the return type has not implemented the move constructor.
Take the following as an example:
10:19:35 Paul Bibbings@JIJOU
/cygdrive/d/CPPProjects/CLCPPM $cat move_everywhere.cpp
// file: move_everywhere.cpp
#include <iostream>
#include <string>
#include <utility>
class MyClass {
std::string s_;
public:
MyClass(std::string s)
: s_(s)
{ std::cout << "ctor\n"; }
MyClass(const MyClass& mc)
: s_(mc.s_)
{ std::cout << "copy\n"; }
MyClass(MyClass&& mc)
: s_(std::move(mc.s_))
{ std::cout << "move\n"; }
};
MyClass func()
{
MyClass tmp("Hello");
return tmp;
}
int main()
{
func();
}
10:19:47 Paul Bibbings@JIJOU
/cygdrive/d/CPPProjects/CLCPPM $i686-pc-cygwin-g++-4.5.0 -O3
-std=c++0x -o move_everywhere move_everywhere.cpp
10:19:59 Paul Bibbings@JIJOU
/cygdrive/d/CPPProjects/CLCPPM $./move_everywhere
ctor
Then, taking the following in stages (accumulatively, using the same
build options to g++):
1. change func to use std::move (note: MyClass has a move constructor):
MyClass func()
{
MyClass tmp("Hello");
return std::move(tmp);
}
10:23:17 Paul Bibbings@JIJOU
/cygdrive/d/CPPProjects/CLCPPM $./move_everywhere
ctor
move
Here, std::move will add an efficiency since MyClass has a move
constructor which, in turn, invokes the move constructor on
std::string. However...
2. remove the move constructor from MyClass:
10:26:30 Paul Bibbings@JIJOU
/cygdrive/d/CPPProjects/CLCPPM $./move_everywhere
ctor
copy
and you have an extra copy over the orignal version of func (without
std::move). This, remember, is with the same optimisation (and, hence,
with the same opportunities for RVO).
3. Change func to return by rvalue-reference:
MyClass&& func()
{
MyClass tmp("Hello");
return std::move(tmp);
}
10:29:30 Paul Bibbings@JIJOU
/cygdrive/d/CPPProjects/CLCPPM $./move_everywhere
ctor
and you have the maximum optimisation again, even though we have not put
back the move constructor. Put the move constructor back in and we are
`cooking on gas' (as we say where I come from :).
So, it seems to me that there is some sense in which doing what you
propose actually interferes with RVO (perhaps) or, at least, introduces
extra copying when used in relation to return by value; and I think I
would have expected that too.
In short, I believe (only) that use of std::move in a return statement
is a form that you would use in relation to a return by rvalue-reference
only in this instance.
In any case, it does not seem that a `blanket' use of std::move is wise
at all and that, like everything else, its use should always be
considered judiciously in relation to the merits of the case.
Regards
Paul Bibbings
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]