2

The following code splits "my string" in a vector<string>:

std::stringstream ss{"my string"};
std::vector<std::string> vec;
std::string tmp;

while (std::getline(ss, tmp, ' ')) {
  vec.push_back(tmp);
}

What I understand is that getline writes its result into tmp and then tmp get pushed into the vector by copying it. But would it be more efficient to do vec.push_back(std::move(tmp)) instead so we avoid the copy?

Jojolatino
  • 602
  • 2
  • 7

2 Answers2

5

What I understand is that getline writes its result into tmp and then tmp get pushed into the vector by copying it.

This is correct. Since tmp is an lvalue, a copy has to be made.

But would it be more efficient to do vec.push_back(std::move(tmp)) instead so we avoid the copy?

Yes-ish. If you use move, instead of copying the whole string you just have a couple pointer/integer swaps. This means it can be much faster. It is safe to use getline to populate the moved from string on each iteration so there is no concern there (source).

The only way it isn't faster is if the string has short string optimization and if the data you are putting in the string is short enough to qualify for it. Then you are dealing with an actually array of characters and you must do a copy since arrays cannot be moved.

NathanOliver
  • 150,499
  • 26
  • 240
  • 331
  • Then would be it be better to do vec.emplace(tmp)? That way a string is constructed within the vector and avoids copying when it is short. – jignatius Oct 15 '19 at 18:08
  • @jignatius That also performs a copy; it won't be any faster or slower than `vec.push_back(tmp)`. – cdhowie Oct 15 '19 at 18:09
3

It's more time-efficient and only slightly more memory-efficient.

Either way, you are allocating some number of strings. Moving the temporary string will simply result in one less allocation for the final iteration of the loop. However, moving can prevent the CPU and RAM I/O overhead of copying memory contents between locations on each iteration.

cdhowie
  • 133,716
  • 21
  • 261
  • 264