[C++] push_back vs emplace_back 차이점

2020. 12. 7. 03:55·Programming/C++

자료를 찾아보면 emplace_back 이 더 우수한 녀석이라거나

생성자 호출 차이라거나 그런 말들이 많이 있으나.

일단 최신 컴파일러 관점에서는 둘 다 아닌것 같다.

 

 

emplace_back 과 push_back 의 차이

item 타입의 생성자가 타입을 인자로 받는다면? push_back 함수는 '객체' 를 집어 넣는 형식으로, 객체가 없이 삽입을 하려면 "임시객체 (rvalue) " 가 있어야 합니다. 또는 암시적 형변환이 가능하다면,

openmynotepad.tistory.com

 

엄준식사생팬 님의 블로그에서 해당 코드를 참조해서 G++ 9 , Visual Studio 2019 (ISO C++14 표준)

에서 테스트 해 보았지만 결과는 같았다.

 

Visual Studio / G++

 

즉, 이유는 모르겠지만 STD 코드가 수정되었음을 추론해 볼 수 있다.

 

그렇게 추가적인 정보를 찾던 중, 상당히 흥미로운 글을 찾았는데,

 

 

emplace_back vs push_back | Gudmundur Blog&Bio

tl;dr emplace_back is often mistaken as a faster push_back, while it is in fact just a different tool. Do not blindly replace push_back by emplace_back, be careful of how you use emplace_back, since it can have unexpected consequences.

gumeo.github.io

Guðmundur Einarsson 님이 2020년 5월 11일에 작성한 글에서 그 차이점을 엿 볼 수 있었다.

 

코드는 다음과 같다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include<vector>
#include<iostream>
 
int main(){
  // Basic example
  std::vector<int> foo;
  foo.push_back(10);
  foo.emplace_back(20);
 
  // More tricky example
  std::vector<std::vector<int>> foo_bar;
  //foo_bar.push_back(10); // Throws error!!!!
  foo_bar.emplace_back(20); // Compiles with no issue
  std::cout << "foo_bar size: " << foo_bar.size() << "\n";
  std::cout << "foo_bar[0] size: " << foo_bar[0].size() << "\n";
  return 0;
}
Colored by Color Scripter
cs

 

해당 코드와 Guðmundur Einarsson 의 언급으로 말미암아 보면,

emplace_back 과 push_back 은 서로 '더 효율적인' 도구 취급따위가 아니라는 점이다.

위 코드를 살펴보면

 

 

1
vector<vector<int>>
cs

 

2중백터로 선언 되어 있는데,

 

이러한 이중 백터를 push_back 으로 넣으려면

 

1
2
vector<int> a  = { 1, 2, 3 };
foo_bar.push_back(a);
cs

 

와 같이 사용 해야 한다

당연히 

 

1
foo_bar.push_back(10)
cs

 

같이 삽입하려면 에러가 발생하는것이 맞다.

 

하지만 이 작업이 .emplace_back 에서는 가능한 것이다.

이것에서 emplace_back 과 push_back 의 차이점이 나타난다.

디버깅 시 emplace_back 의 경우 20개의 vector 공간이 생성된것을 확인할 수 있다.

 

emplace_back 으로 초기화한 20개의 vector.

 

나는 솔직히 이딴것도 왜 만들어 둔지 모르겠지만, 일단 이런게 있다고 한다.

(아직 내 지식의 부족인가 보다)

 

이 외에도 emplace back 은 언제 사용할 수 있냐면.

emplace_back 의 코드를 살펴보면 알 수 있는데,

 

emplace_back, push_back

 

emplace_back 의 경우 multi-parameter 가 가능하게 코딩 되어 있으므로,

 

 즉

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>
#include <vector>
 
class Image {
    size_t ww;
    size_t hh;
public:
    Image(size_t w, size_t h) : ww(w), hh(h)
    {
 
    }
};
 
int main()
{
    std::vector<Image> images;
    images.emplace_back(2000, 1000);
    //images.push_back(2000, 1000); // error
 
    return 0;
}
Colored by Color Scripter
cs

 

이렇게 다중 Parameter 를 Push_back 과 대조되게 사용하는것이 가능하다.

원래 Push_back 을 이용하려면 불필요하게 Structor 를 만들어 사용 하였는데,

emplace_back 을 사용하면서 다중 파라미터에서도 영향 없이 사용할 수 있는 것이다.

 

 

주의점

 

 

출력되는 에러 메세지가 직관적이지 않다.

초보자는 방대한 코드속에서 이런 에러가 발생하면

어디서 부터 잘못 되었는지 찾기 힘들어 질 수 있다.

 

더군다나

1
2
3
4
5
6
7
8
9
10
11
#include <vector>
class A {
public:
    explicit A(int /*unused*/) {}
};
int main() {
    double foo = 4.5;
    std::vector<A> a_vec{};
    a_vec.emplace_back(foo); // No warning with Wconversion
    //A a(foo); // Gives compiler warning with Wconversion as expected
}
Colored by Color Scripter
cs

 

explict 예약어를 사용해 자동 형변환을 방지했음에도 불구하고,

emplace_back 은 이를 씹고 진행한다. (push_back 에서는 에러 발생)

 

때문에 Guðmundur Einarsson 님은 가급적 애매한 상황에서는 Push_back 을 사용하는것을 추천하며,

나아가 emplace_back 을 사용하려면 emplace_back 이 어떻게 작동하는지

이해하고 사용하는것이 필요하다 기재 하였으며, 나도 이에 공감한다.

 

 

끝

저작자표시 동일조건 (새창열림)

'Programming > C++' 카테고리의 다른 글

[C++] TCP 통신  (0) 2020.12.20
[C++] 람다식 mutable 의 쓰임세.  (0) 2020.12.07
[C++] C4819 Warning 해결 방법, 한글 깨짐 문제  (0) 2020.12.03
[C++] constexpr 사용하기.  (0) 2020.11.22
[C++] 함수 포인터  (0) 2020.11.01
'Programming/C++' 카테고리의 다른 글
  • [C++] TCP 통신
  • [C++] 람다식 mutable 의 쓰임세.
  • [C++] C4819 Warning 해결 방법, 한글 깨짐 문제
  • [C++] constexpr 사용하기.
Cyp
Cyp
  • Cyp
    Cyp Software Blog
    Cyp
  • 전체
    오늘
    어제
    • Cyp Blog (163)
      • Artificial Intelligence (40)
        • Article (21)
        • Post (2)
        • Basic (14)
        • Preferences (3)
      • Cyber Security (1)
      • Programming (46)
        • C++ (21)
        • C# (19)
        • Python (2)
        • Rust (0)
        • Java (1)
      • Algorithm (17)
        • BACKJOON (15)
      • Operating System (14)
        • WSL (2)
        • Windows (1)
        • Linux (5)
        • Security (3)
      • Tools (26)
        • Docker (3)
        • DataBase (2)
        • SSH (1)
        • Doxygen (2)
        • Etc (17)
      • Miscellaneous (19)
        • Book (2)
        • Hardware (2)
        • Hevel (1)
  • 블로그 메뉴

    • Home
    • Guest Book
  • 공지사항

    • 블로그 업데이트 노트
    • 블로그 운영방침
  • 인기 글

  • 태그

    Bom
    utf-8 bom
    y-cruncher
    UTF-8 without BOM
    C4819
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.4
Cyp
[C++] push_back vs emplace_back 차이점
상단으로

티스토리툴바