push_backとemplace_backの違い

結論

  • emplace_back(3) v.s. push_back(3)
    emplace_backではコンストラクタだけが呼ばれてムーブコンストラクタが呼ばれない。push_backはコンストラクタが呼ばれた後にムーブコンストラクタが呼ばれる。

  • m=MyClass(3)と定義した後のemplace_back(m) v.s. push_back(m)
    emplace_backpush_backで差はない。
    mを作る時にコンストラクタが呼ばれ、詰める時にコピーコンストラクタが呼ばれる

  • emplace_back(MyClass(3)) v.s. push_back(MyClass(3))
    emplace_backpush_backで差はない。
    コンストラクタの後にムーブコンストラクタが呼ばれる

  • m=MyClass(3)と定義した後のemplace_back(std::move(m)) v.s. push_back(std::move(m))
    emplace_backpush_backで差はない。
    mを作る時にコンストラクタが呼ばれ、詰める時にムーブコンストラクタが呼ばれる

#include <vector>
#include <iostream>

class MyClass {
public:
  int n;
  MyClass(int n) : n(n) {
    std::cout << "Constructor (n=" << n << ")" << std::endl;
  }
  MyClass(const MyClass & a) {
    n = a.n;
    std::cout << "Copy constructor (n=" << n << ")" << std::endl;
  }
  MyClass(MyClass && a) {
    n = a.n;
    std::cout << "Move constructor (n=" << n << ")" << std::endl;
  }
};

int main() {
  MyClass m1(3);
  MyClass m2(33);
  MyClass m3(333);
  std::vector<MyClass> vec;
  // 配列サイズが足りずに途中でコピーされるのを防ぐため大きめにreserveしておく                                               
  vec.reserve(100);
  std::cout << "=== push_back ====" << std::endl;
  std::cout << "- feed variable" << std::endl;
  vec.push_back(m1);
  std::cout << "- feed direct construct object" << std::endl;
  vec.push_back(MyClass(4));
  std::cout << "- feed move object" << std::endl;
  vec.push_back(std::move(m2));
  std::cout << "- feed construct element only" << std::endl;
  vec.push_back(4);

  std::cout << "=== emplace_back ====" << std::endl;
  std::cout << "- feed variable" << std::endl;
  vec.emplace_back(m1);
  std::cout << "- feed direct construct object" << std::endl;
  vec.emplace_back(MyClass(6));
  std::cout << "- feed move object" << std::endl;
  vec.emplace_back(std::move(m3));
  std::cout << "- feed construct element only" << std::endl;
  vec.emplace_back(7);

  return 0;
}

出力例

Constructor (n=3)
Constructor (n=33)
Constructor (n=333)
=== push_back ====
- feed variable
Copy constructor (n=3)
- feed direct construct object
Constructor (n=4)
Move constructor (n=4)
- feed move object
Move constructor (n=33)
- feed construct element only
Constructor (n=4)
Move constructor (n=4)
=== emplace_back ====
- feed variable
Copy constructor (n=3)
- feed direct construct object
Constructor (n=6)
Move constructor (n=6)
- feed move object
Move constructor (n=333)
- feed construct element only
Constructor (n=7)