3

Using push_back with rvalue references?

I have the following code:

csvData.push_back(CsvDataSet(csvBlock));

Should I instead do this:

csvData.push_back(std::move(CsvDataSet(csvBlock)));

That way I save one copy operation.

user3111311
  • 7,583
  • 7
  • 33
  • 48

2 Answers2

10

Assuming CsvDataSet to be a class: No, you shouldn't. CsvDataSet(csvBlock) is already an rvalue. More precisely, it is an prvalue.

Therefore in both cases, void std::vector::push_back( T&& value ); will be called.

Shoe
  • 74,840
  • 36
  • 166
  • 272
6

I think in your case you should use emplace_back().

"Appends a new element to the end of the container. The element is constructed in-place, i.e. no copy or move operations are performed. The constructor of the element is called with exactly the same arguments that are supplied to the function."

Not sure, but I think it is equivalent for using push_back(std::move(T())), but maybe the downvoter correct me, please. Clarification the result should be the same, but emplace forwards arguments to constructor and constructs elements in place, while push_back calls move constructor, or normal one and then moves object.

Edit: if the downvoter agrees with the reasoning presented by @user3111311 below I urge to read Example section in emplace_back().

luk32
  • 15,812
  • 38
  • 62
  • 1
    emplace_back is redundant in c++11, push_back should be used instead – user3111311 Jan 17 '14 at 15:23
  • 1
    @user3111311 What?! Can you back it up? It was introduced in c++11. Why would the standard committee include something redundant? Is that an aesthetic opinion? – luk32 Jan 17 '14 at 15:26
  • 1
    emplace_back was meant to be an "efficient" version of push_back. Now that we have push_back for rvalue references, it is not needed. It is kept in c++11 for backwards compatibility. – user3111311 Jan 17 '14 at 15:29
  • 1
    @user3111311 For backwards compatibility with what? Both `emplace_back` and `void push_back( T&& value )` are introduced in the same version of standard. Unless cppreference is wrong. There is no "now". `Emplace` constructs object in-place, `push_back` moves it. Therefore in your case you get called a constructor, and move instead of just constructor called. – luk32 Jan 17 '14 at 15:32
  • 6
    @user3111311 `emplace_back` is not redundant in C++11. There are specific forms of `emplace_back` that was provided by different compilers that are non comformant and redundant ([see this](http://stackoverflow.com/questions/4303513/push-back-vs-emplace-back)). However the correct form of `emplace_back` taking the constructor parameters directly e.g. `csvData.emplace_back(csvBlock)` is **not** redundant. It will construct the object in place instead of performing a move construct as `void push_back(T&&)` – Felix Glas Jan 17 '14 at 15:33
  • 1
    @user3111311 IT is in fact *`push_back`* that is redundant in C++11, since `emplace_back` encompasses its functionality. – Casey Jan 17 '14 at 16:08
  • 1
    @Casey I wouldn't go as far. `emplace_back` just forwards arguments to the constructor, u might want to move an already constructed the element onto the list. `emplace` cannot do that. But calling constructor as argument in `push_back()` seem of little sense to me. – luk32 Jan 17 '14 at 16:18
  • 2
    @luk32 Yes, `emplace` can do that. Passing a `T const&` or `T&&` to `emplace_back` has identical effect to passing a `T const&` or `T&&` to `push_back`. – Casey Jan 17 '14 at 17:40