2

I have the following function inside a class

  void add_state(std::string &&st) {
    state.emplace_back(st);           // state is a vector
  }

st is an l-value (rvalue reference to a string in this case) based on my understanding. If, I want to move st into the last element in state, should I be using state.emplace_back(std::move(st))? What happens if I leave it the way it's written above?

EDIT 1 (example of how add_state is called):

// do a series of operations to acquire std::string str
add_state(std::move(str)); 
// also note that str will never be used again after passing it into add_state

Would it be better if I made add_state(std::string &st) instead? In this case, I think I can just simply call it with add_state(str)?

1
  • I would like to hear more about the use of r-value references, std::move and emplace_back, because it seems like and important use case. If I have a function call returning a value, and I want to store it in an array, how to I ensure the objects are instantiated straight inside the array? vec.emplace_back(mkobj());? `obj&& o=mkobj(); vec.emplace_bac(std::move(o))``? When is it even necessary, an when can I be sure it will be optimized already? Commented Nov 2, 2020 at 13:33

1 Answer 1

7

[...] should I be using state.emplace_back(std::move(st))?

Yes.

What happens if I leave it the way it's written above?

You have correctly identified that st is an lvalue, so it gets copied.

Would it be better if I made add_state(std::string &st) instead? In this case, I think I can just simply call it with add_state(str)?

You could, but you shouldn't. std::move is just type juggling, it does not do anything by itself (in particular, it doesn't move anything). The actual operation happens inside std::string::basic_string(std::string &&) which is called by emplace_back after it receives the std::string &&. Making your own parameter an lvalue reference has no effect other than surprising the caller, who gets their std::string eaten without an std::move on their part.

1
  • So let me give some more background because I'm not sure if I'm doing this optimally. When calling add_state, I had to cast an lvalue to an xvalue and pass this into add_state. Note that the argument being passed into add_state will never be used again. And then inside add_state, I have to perform another std::move, as you just stated. So that's 2 moves. Could I achieve the same behavior if I simply passed the lvalue by plain vanilla reference, and then move it inside the function? In this case, I would only be performing 1 move? I'll edit this into the OP to make it clearer.
    – 24n8
    Commented Apr 21, 2020 at 14:43

Not the answer you're looking for? Browse other questions tagged or ask your own question.