자료를 찾아보면 emplace_back 이 더 우수한 녀석이라거나
생성자 호출 차이라거나 그런 말들이 많이 있으나.
일단 최신 컴파일러 관점에서는 둘 다 아닌것 같다.
엄준식사생팬 님의 블로그에서 해당 코드를 참조해서 G++ 9 , Visual Studio 2019 (ISO C++14 표준)
에서 테스트 해 보았지만 결과는 같았다.
즉, 이유는 모르겠지만 STD 코드가 수정되었음을 추론해 볼 수 있다.
그렇게 추가적인 정보를 찾던 중, 상당히 흥미로운 글을 찾았는데,
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;
}
|
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 은 언제 사용할 수 있냐면.
emplace_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;
}
|
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
}
|
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 |