C++ vector의 emplace_back vs push_back
개요
std::vector
에서 emplace_back
과 push_back
은 모두 컨테이너의 끝에 요소를 추가하는 멤버 함수입니다. 이 두 함수는 비슷해 보이지만 내부 동작 방식에서 중요한 차이점이 있습니다. emplace_back
은 C++11에서 도입된 기능으로, 불필요한 복사나 이동 연산을 피하고 직접 객체를 생성할 수 있게 해줍니다.
C++ 버전별 주요 키워드 도입 시기
- C++98/03:
push_back()
만 사용 가능 - C++11:
emplace_back()
도입, 완벽한 전달(perfect forwarding) 지원 - C++17:
emplace_back()
이 참조를 반환하도록 변경
내용 설명
push_back의 동작 방식
- 전달된 인자로 임시 객체를 생성합니다.
- 이 임시 객체를 벡터 내부로 이동하거나 복사합니다.
- 임시 객체는 파괴됩니다.
emplace_back의 동작 방식
- 전달된 인자들을 완벽한 전달(perfect forwarding)을 사용하여
벡터 내부에서 직접 객체를 생성합니다. - 임시 객체 생성 및 파괴 과정이 없어 효율적입니다.
주요 차이점
emplace_back
은 생성자 인자만 전달하면 벡터 내에서 직접 객체를 생성push_back
은 이미 생성된 객체나 임시 객체를 전달해야 함emplace_back
이 일반적으로 더 효율적(특히 복사/이동 비용이 큰 객체의 경우)emplace_back
은 explicit 생성자와 함께 사용할 수 없음
예제 코드
#include <vector>
#include <string>
#include <iostream>
class MyObject {
public:
MyObject(int id, const std::string& name) : id_(id), name_(name) {
std::cout << "MyObject constructed: " << name_ << std::endl;
}
// 복사 생성자
MyObject(const MyObject& other) : id_(other.id_), name_(other.name_) {
std::cout << "MyObject copied: " << name_ << std::endl;
}
// 이동 생성자
MyObject(MyObject&& other) noexcept : id_(other.id_), name_(std::move(other.name_)) {
std::cout << "MyObject moved: " << name_ << std::endl;
}
private:
int id_;
std::string name_;
};
int main() {
std::vector<MyObject> objects;
std::cout << "=== Using emplace_back ===\n";
objects.emplace_back(1, "First Object"); // 직접 생성
std::cout << "\n=== Using push_back ===\n";
objects.push_back(MyObject(2, "Temporary Object")); // 임시 객체 생성 후 이동
return 0;
}
실행 결과
=== Using emplace_back ===
MyObject constructed: First Object
=== Using push_back ===
MyObject constructed: Temporary Object
MyObject moved: Temporary Object
활용팁
- 효율성:
emplace_back
은 불필요한 복사/이동을 피할 수 있어 성능상 이점이 있습니다. - 가독성:
push_back
이 더 명시적인 경우가 있어, 코드 가독성을 고려하여 선택하세요. - explicit 생성자:
emplace_back
은 explicit 생성자와 함께 사용할 수 없습니다. - C++17 이상:
emplace_back
은 참조를 반환하므로 메서드 체이닝이 가능합니다. - 기본 타입: 기본 타입(int, double 등)의 경우 성능 차이가 거의 없습니다.
- 주의사항:
emplace_back
은 perfect forwarding을 사용하므로,vector<bool>
과 함께 사용할 때는 주의가 필요합니다.
결론
emplace_back
은 객체 생성을 위한 인자만 전달하면 되므로 더 효율적이고 현대적인 C++ 스타일입니다. 하지만 코드의 명확성이 더 중요한 경우나 explicit 생성자와 함께 사용해야 할 때는 push_back
을 사용하는 것이 더 나을 수 있습니다. 프로젝트의 코딩 표준과 요구사항에 맞게 적절히 선택하여 사용하시기 바랍니다.
'개발 > C++ (98,03,11,14,17,20,23)' 카테고리의 다른 글
Modern C++ : std::vector (98, 11, 14, 17, 20) (0) | 2025.08.21 |
---|---|
Modern C++ : template, std::span (20) (0) | 2025.08.20 |
Modern C++ : perfect forwarding (11) (1) | 2025.08.19 |
Modern C++ : rvalue reference summary (11) (2) | 2025.08.18 |
Modern C++ : lvalue, rvalue, value category (98, 11) (2) | 2025.08.17 |
Modern C++ : rvalue reference (98, 11) (1) | 2025.08.16 |
Modern C++ : lvalue rvalue reference (98, 11) (2) | 2025.08.15 |
Modern C++ : dynamic heap memory allocation (98, 11, 14) (1) | 2025.08.14 |