본문 바로가기
개발/C++ (98,03,11,14,17,20,23)

Modern C++ : std::vector, emplace_back vs push_back (98, 11, 17)

by snowoods 2025. 8. 22.

Modern C++

C++ vector의 emplace_back vs push_back

 

개요

std::vector에서 emplace_backpush_back은 모두 컨테이너의 끝에 요소를 추가하는 멤버 함수입니다. 이 두 함수는 비슷해 보이지만 내부 동작 방식에서 중요한 차이점이 있습니다. emplace_back은 C++11에서 도입된 기능으로, 불필요한 복사나 이동 연산을 피하고 직접 객체를 생성할 수 있게 해줍니다.

 

C++ 버전별 주요 키워드 도입 시기

  • C++98/03: push_back()만 사용 가능
  • C++11: emplace_back() 도입, 완벽한 전달(perfect forwarding) 지원
  • C++17: emplace_back()이 참조를 반환하도록 변경

 

내용 설명

push_back의 동작 방식

  1. 전달된 인자로 임시 객체를 생성합니다.
  2. 이 임시 객체를 벡터 내부로 이동하거나 복사합니다.
  3. 임시 객체는 파괴됩니다.

 

emplace_back의 동작 방식

  1. 전달된 인자들을 완벽한 전달(perfect forwarding)을 사용하여
    벡터 내부에서 직접 객체를 생성합니다.
  2. 임시 객체 생성 및 파괴 과정이 없어 효율적입니다.

 

주요 차이점

  • 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

 

활용팁

  1. 효율성: emplace_back은 불필요한 복사/이동을 피할 수 있어 성능상 이점이 있습니다.
  2. 가독성: push_back이 더 명시적인 경우가 있어, 코드 가독성을 고려하여 선택하세요.
  3. explicit 생성자: emplace_back은 explicit 생성자와 함께 사용할 수 없습니다.
  4. C++17 이상: emplace_back은 참조를 반환하므로 메서드 체이닝이 가능합니다.
  5. 기본 타입: 기본 타입(int, double 등)의 경우 성능 차이가 거의 없습니다.
  6. 주의사항: emplace_back은 perfect forwarding을 사용하므로, vector<bool>과 함께 사용할 때는 주의가 필요합니다.

 

결론

emplace_back은 객체 생성을 위한 인자만 전달하면 되므로 더 효율적이고 현대적인 C++ 스타일입니다. 하지만 코드의 명확성이 더 중요한 경우나 explicit 생성자와 함께 사용해야 할 때는 push_back을 사용하는 것이 더 나을 수 있습니다. 프로젝트의 코딩 표준과 요구사항에 맞게 적절히 선택하여 사용하시기 바랍니다.