c++ vector.emplace_back()

std::vector::emplace_back

 

지원 버전

C++ 11

 

클래스

std::vector

 

함수

template<class.. Args>
void emplace_back(Args&&... args);
※ 가변인자를 받는다는 것이 특징이다.

 

설명

emplace_back은 vector의 마지막 요소 뒤에 추가해주는 함수이다. 이 함수는 두가지 특징을 가진다.

  1. 생성자를 위한 파라미터들을 직접 받는다.
        => 생성자 파라미터 순서대로 넣어줘야 한다.
  2. vector 내부에서 객체를 직접 생성한다.
        => vector 외부에서 객체관리가 필요 없다.
  3. 함수 호출 수를 줄여서 성능을 높인다.
        => vector 외부에서 객체를 만들어서 넣으면 최종 2번 호출하지만, vector 내부에서 객체를 만들어서 넣으므로 최종 1번 호출한다. 

emplace_back은 push_back과 함께 보면 이해를 도울 것으로 생각된다. (C++98의) push_back은 (C++ 11의) emplace_back과는 다르게 동작한다. push_back은 함수 밖에서 객체를 생성한 후 입력 파라미터값으로 넣어주면 push_back 함수 안에서는 객체의 이동생성자를 호출해서 동작한다. 반면에, emplace_back은 함수 밖에서 객체를 생성하지 않고 객체 생성에 필요한 값 자체를 입력 파라미터값으로 받고 있기 때문에 emplace_back 함수안에서 객체의 이동생성자 한번만 호출하면 되는 것이다.

 

 

예제

아래 코드는 vector의 요소값을 emplace_back과 push_back를 사용해서 넣었을 때, 생성자가 몇 번 호출되는지를 보려는 것이다. emplace_back는 vector의 함수 중 하나로 사용법은 어렵지 않기 때문에, emplace_back이 어떤 특징이 있는지 이해하는 것을 목적으로 작성했다. 아래 예제의 각 함수를 호출했을 때 아래 순서로 호출된다. (참고로, 코드가 길어서 소멸자는 사용하지 않았다.)

- vector.emplace_back()
  1. constructor 호출 (=생성)
  2. move constructor 호출 (=생성) 
  3. move destructor 호출 (=파괴)
  4. destructor 호출 (=파괴)

- vector.push_back()
  1. constructor 호출 (=생성)
  2. destructor 호출 (=파괴)

 

 

joker.hpp

#include <iostream>
#include <string>

using namespace std;

class Joker
{
    private:
        int _a;
        string _b;

    public:
        // constructor
        Joker(const int a, const string& b)
        : _a(a)
        , _b(b)
        {
            cout << _a << " " << _b << " at constructr" << endl;
        }

        // move constructor
        Joker(Joker&& jk)
        : _a(jk._a)
        , _b(jk._b)
        {
            cout << _a << " " << _b << " at move constructor" << endl;
        }

        ~Joker()
        {
          cout << _a << " " << _b << " at destructor" << endl;
        }
};

 

main.cpp

#include <vector>
#include "joker.hpp"

using namespace std;

void emplace_back_test() {
  vector<Joker> v;

  // constructor 호출
  v.emplace_back(47, "emplace_back");
}

void push_back_test() {
  vector<Joker> v;

  // constructor & move constructor 호출
  v.push_back(Joker(23, "push_back"));
}

int main()
{
    emplace_back_test();
    push_back_test();

    return 0;
}

 

실행결과 

47 emplace_back at constructr
47 emplace_back at destructor
23 push_back at constructr
23 push_back at move constructor
23 push_back at destructor
23 push_back at destructor