C++의 std::vector에서 emplace_back과 push_back은 둘 다 컨테이너의 끝에 요소를 추가하는 함수이지만, 객체 생성 방식에서 중요한 차이점이 있습니다. 이 차이가 성능에 영향을 미칠 수 있습니다.
push_back의 동작 방식push_back은 새로운 객체를 추가할 때 "복사(copy)" 또는 "이동(move)" 생성자를 사용합니다.
push_back(const T& val): val을 인자로 받아서, val의 복사본을 컨테이너 내부에 생성합니다.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에 이동 (이동 생성자 호출)
동작 단계:
MyClass(3, 4)를 생성합니다.push_back을 호출합니다.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)를 직접 생성 (생성자 호출)
동작 단계: