C++의 std::vector에서 emplace_backpush_back은 둘 다 컨테이너의 끝에 요소를 추가하는 함수이지만, 객체 생성 방식에서 중요한 차이점이 있습니다. 이 차이가 성능에 영향을 미칠 수 있습니다.

push_back의 동작 방식

push_back은 새로운 객체를 추가할 때 "복사(copy)" 또는 "이동(move)" 생성자를 사용합니다.

  1. push_back(const T& val): val을 인자로 받아서, val복사본을 컨테이너 내부에 생성합니다.
  2. push_back(T&& val): val을 인자로 받아서, val을 컨테이너 내부로 **이동(move)**시킵니다.

push_back을 호출할 때 이미 외부에서 객체가 생성되어 있어야 합니다.

예시:

struct MyClass {
    MyClass(int a, int b) { /*...*/ }
    MyClass(const MyClass& other) { /* 복사 생성자 */ }
    MyClass(MyClass&& other) { /* 이동 생성자 */ }
};

std::vector<MyClass> vec;

// 1. push_back(const T&) - 복사 생성
MyClass obj(1, 2);  // 객체 생성
vec.push_back(obj); // obj를 복사하여 vec에 추가 (복사 생성자 호출)

// 2. push_back(T&&) - 이동 생성
vec.push_back(MyClass(3, 4)); // 임시 객체를 생성하고, 이 임시 객체를 vec에 이동 (이동 생성자 호출)

동작 단계:

  1. 외부에서 객체 MyClass(3, 4)를 생성합니다.
  2. push_back을 호출합니다.
  3. std::vector가 내부적으로 메모리 공간을 확보하고, 외부에서 생성된 객체를 그 공간으로 이동시킵니다.

이동 생성자가 없는 경우에는 복사 생성자가 호출됩니다. 이 경우 불필요한 객체 생성/소멸이 발생하여 성능 저하의 원인이 될 수 있습니다.

emplace_back의 동작 방식

emplace_back은 인자를 받아, 컨테이너의 메모리 공간에 직접 "인플레이스(in-place)" 생성을 수행합니다.

emplace_back은 함수 인자로 객체 생성자의 인자들을 직접 받습니다. 그리고 이 인자들을 std::vector가 내부적으로 가지고 있는 메모리 공간에 전달하여, push_back처럼 임시 객체를 만들고 복사/이동하는 과정 없이 바로 객체를 생성합니다.

예시:

struct MyClass {
    MyClass(int a, int b) { /*...*/ }
    MyClass(const MyClass& other) { /* 복사 생성자 */ }
    MyClass(MyClass&& other) { /* 이동 생성자 */ }
};

std::vector<MyClass> vec;

// emplace_back(Args...) - 직접 생성
vec.emplace_back(1, 2); // vector 내부에 MyClass(1, 2)를 직접 생성 (생성자 호출)

동작 단계: