Reputation: 1930
Consider:
struct Foo {
Foo () { std::cout << "default ctor" << std::endl; }
Foo (const Foo&) { std::cout << "copy ctor" << std::endl; }
Foo& operator= (const Foo&) { std::cout << "copy op" << std::endl; return *this; }
Foo (Foo&&) { std::cout << "move ctor" << std::endl; }
Foo& operator= (Foo&&) { std::cout << "move op" << std::endl; return *this; }
~Foo () { std::cout << "dtor" << std::endl; }
};
Foo process1 (Foo&& foo) {
return foo;
}
Foo process2 (Foo&& foo) {
return std::move (foo);
}
and usage:
Foo foo {};
foo = process1 (std::move (foo));
gives result:
default ctor
copy ctor
move op
dtor
dtor
and usage:
Foo foo {};
foo = process2 (std::move (foo));
gives result:
default ctor
move ctor
move op
dtor
dtor
Which one is preferred one (process1 or process2)?
Does it mean that in the first example (process1) if I pass object by rvalue reference to the function, which returns an Object, the copy will be made if I do not use std::move()
?
Compiler: GCC 5.2.1
Upvotes: 2
Views: 171
Reputation: 76297
In the first version
Foo process1 (Foo&& foo) {
return foo;
}
you pass it as an rvalue reference, but by the "if it has a name" heuristic, it is treated as an lvalue within the function, hence the copy ctor.
The second version "remakes" this an rvalue using std::move
(which is exactly what it is meant for). Thus the copy ctor is avoided.
It's pretty reasonable to expect that a move will not be more expensive than a copy, so, given a real-life situation boiling down to this, you might prefer the second version.
Upvotes: 6