10

For move enabled classes is there a difference between this two?

struct Foo {
typedef std::vector<std::string> Vectype;
Vectype m_vec;
//this or
void bar(Vectype&& vec)
{
   m_vec = std::move(vec);
}
//that
void bar(Vectype vec)
{
    m_vec = std::move(vec);
}
};
int main()
{
   Vectype myvec{"alpha","beta","gamma"};
   Foo fool; 
   fool.bar(std::move(myvec));
}

My understanding is that if you use a lvalue myvec you also required to introduce const Vectype& version of Foo::bar() since Vectype&& won't bind. That's aside, in the rvalue case, Foo::bar(Vectype) will construct the vector using the move constructor or better yet elide the copy all together seeing vec is an rvalue (would it?). So is there a compelling reason to not to prefer by value declaration instead of lvalue and rvalue overloads? (Consider I need to copy the vector to the member variable in any case.)

Cassio Neri
  • 19,583
  • 7
  • 46
  • 68
hurcan solter
  • 127
  • 1
  • 10

3 Answers3

6

The pass-by-value version allows an lvalue argument and makes a copy of it. The rvalue-reference version can't be called with an lvalue argument.

Use const Type& when you don't need to change or copy the argument at all, use pass-by-value when you want a modifiable value but don't care how you get it, and use Type& and Type&& overloads when you want something slightly different to happen depending on the context.

aschepler
  • 70,891
  • 9
  • 107
  • 161
3

The pass-by-value function is sufficient (and equivalent), as long as the argument type has an efficient move constructor, which is true in this case for std::vector.

Otherwise, using the pass-by-value function may introduce an extra copy-construction compared to using the pass-by-rvalue-ref function.

See the answer https://stackoverflow.com/a/7587151/1190077 to the related question Do I need to overload methods accepting const lvalue reference for rvalue references explicitly? .

Community
  • 1
  • 1
Hugues
  • 2,865
  • 1
  • 27
  • 39
2

Yes, the first one (Vectype&& vec) won't accept a const object or simply lvalue.

If you want to save the object inside like you do, it's best to copy(or move if you pass an rvalue) in the interface and then move, just like you did in your second example.

Bartek Banachewicz
  • 38,596
  • 7
  • 91
  • 135