Moving arguments or passing them the usual C++98/03 way?

argument-passing, c++, c++11, move-semantics

Solution

I'd recommend against making this complicated by choosing to use `Person(move(name), move(surname))` without a particular reason for doing so.

Consider a simple loop reading names and constructing Person objects:

string name, surname;
while ((cin >> name) && (cin >> surnam)) {
  Person p(name, surname);
  // ...
}

This does result in copies of `name` and `surname` for each `Person`, but the allocation behavior in this context actually turns out to be efficient. Since `name` and `surname` retain their own buffers, those buffers just get reused for the next input operation, which means that once those buffers are large enough no additional allocations occur just for the input. So on average you should get just the one allocation per `name` and `surname` that occurs during the copy.

If you use `move()` to save the one allocation during the copy, then allocation is done during the input operation instead and you can possibly get multiple allocations as the buffer grows dynamically while reading. That means you could potentially do many more allocations when using `move()`.

Furthermore, the copy allocates the minimal amount of memory needed, whereas the strings used in the input operation may have 'extra' based on whatever dynamic growth strategy `string` employs. Therefore explicit moves could result in greater memory usage by persisting that 'extra' into the `Person` objects.

So by default just do what's simple and straightforward. I think using `move()` by default here is a case of premature optimization.

Problem

Suppose that there is a `Person` class like this: ``` // "string" is std::string, "move" is std::move class Person { public: // C++11 way: pass by value and std::move() from the value Person(string name, string surname) : m_name(move(name)), m_surname(move(surname)) {} .... private: string m_name; string m_surname; }; ``` Suppose that I read the `name` and `surname` values from some source (e.g. a file) in some loop, and in each loop iteration I want to create a `Person` with these read values (and e.g. push the created `Person` in some container). Is it better to call `Person` constructor in the usual way: ``` Person(name, surname) ``` or using `std::move` for the arguments? ``` Person(move(name), move(surname)) ```

Original source

Related problems