Programing

push_back 대 emplace_back

lottogame 2020. 10. 2. 21:21
반응형

push_back 대 emplace_back


나는 조금의 차이에 대한 혼란 스러워요 push_backemplace_back.

void emplace_back(Type&& _Val);
void push_back(const Type& _Val);
void push_back(Type&& _Val);

push_backrvalue 참조를받는 오버로드 가 있기 때문에 그 목적이 무엇인지 잘 모르겠습니다 emplace_back.


방문자가 말한 것 외에도 :

void emplace_back(Type&& _Val)MSCV10에서 제공하는 기능 push_back(Type&& _Val).

그러나 실제 C ++ 0x 형식 emplace_back은 정말 유용합니다. void emplace_back(Args&&...);

a를 취하는 대신 value_type가변적 인 인수 목록을 사용하므로 이제 인수를 완벽하게 전달하고 임시없이 컨테이너에 객체를 직접 구성 할 수 있습니다.

RVO와 이동 시맨틱이 아무리 영리 해져도 push_back이 불필요한 복사 (또는 이동)를 만들 가능성이있는 복잡한 경우가 있기 때문에 유용합니다. 예를 들어,의 기존 insert()기능 std::map을 사용하는 경우 임시를 만들어야합니다.이 임시 파일 std::pair<Key, Value>은에 복사 된 다음지도에 복사됩니다.

std::map<int, Complicated> m;
int anInt = 4;
double aDouble = 5.0;
std::string aString = "C++";

// cross your finger so that the optimizer is really good
m.insert(std::make_pair(4, Complicated(anInt, aDouble, aString))); 

// should be easier for the optimizer
m.emplace(4, anInt, aDouble, aString);

그렇다면 MSVC에서 올바른 버전의 emplace_back을 구현하지 않은 이유는 무엇입니까? 사실, 너무 오래전에 저를 괴롭 혔기 때문에 Visual C ++ 블로그 에서 같은 질문을했습니다 . 다음은 Microsoft에서 Visual C ++ 표준 라이브러리 구현의 공식 관리자 인 Stephan T Lavavej의 답변입니다.

Q : 베타 2 emplace 함수는 현재 일종의 자리 표시 자일까요?

A : 아시다시피 가변 템플릿은 VC10에서 구현되지 않습니다. make_shared<T>(), 튜플 및 .NET의 새로운 항목에 대한 전 처리기 기계로 시뮬레이션합니다 <functional>. 이 전 처리기 기계는 사용 및 유지 관리가 상대적으로 어렵습니다. 또한 반복적으로 하위 헤더를 포함해야하므로 컴파일 속도에 큰 영향을줍니다. 시간 제약과 컴파일 속도 문제의 조합으로 인해 emplace 함수에서 가변 템플릿을 시뮬레이션하지 않았습니다.

가변 템플릿이 컴파일러에서 구현되면 emplace 함수를 포함하여 라이브러리에서이를 활용할 수 있습니다. 우리는 준수를 매우 중요하게 생각하지만 안타깝게도 모든 것을 한꺼번에 할 수는 없습니다.

이해할 수있는 결정입니다. 전 처리기 끔찍한 트릭으로 가변 템플릿을 에뮬레이트하려고 한 번만 시도한 모든 사람은이 항목이 얼마나 역겨운 지 알고 있습니다.


emplace_back유형의 인수를 가져서는 안되며 vector::value_type대신 추가 된 항목의 생성자에 전달되는 가변 인수를 사용합니다.

template <class... Args> void emplace_back(Args&&... args); 

전달하는 것이 가능하다 value_type복사 생성자로 전달 될있다.

인수를 전달하기 때문에 이는 rvalue가없는 경우 컨테이너가 이동 된 복사본이 아닌 "복사 된"복사본을 저장한다는 것을 의미합니다.

 std::vector<std::string> vec;
 vec.emplace_back(std::string("Hello")); // moves
 std::string s;
 vec.emplace_back(s); //copies

그러나 위의 내용은하는 것과 동일해야합니다 push_back. 아마도 다음과 같은 사용 사례를위한 것입니다.

 std::vector<std::pair<std::string, std::string> > vec;
 vec.emplace_back(std::string("Hello"), std::string("world")); 
 // should end up invoking this constructor:
 //template<class U, class V> pair(U&& x, V&& y);
 //without making any copies of the strings

에 대한 최적화 emplace_back는 다음 예에서 설명 할 수 있습니다.

For emplace_back constructor A (int x_arg) will be called. And for push_back A (int x_arg) is called first and move A (A &&rhs) is called afterwards.

Of course, the constructor has to be marked as explicit, but for current example is good to remove explicitness.

#include <iostream>
#include <vector>
class A
{
public:
  A (int x_arg) : x (x_arg) { std::cout << "A (x_arg)\n"; }
  A () { x = 0; std::cout << "A ()\n"; }
  A (const A &rhs) noexcept { x = rhs.x; std::cout << "A (A &)\n"; }
  A (A &&rhs) noexcept { x = rhs.x; std::cout << "A (A &&)\n"; }

private:
  int x;
};

int main ()
{
  {
    std::vector<A> a;
    std::cout << "call emplace_back:\n";
    a.emplace_back (0);
  }
  {
    std::vector<A> a;
    std::cout << "call push_back:\n";
    a.push_back (1);
  }
  return 0;
}

output:

call emplace_back:
A (x_arg)

call push_back:
A (x_arg)
A (A &&)

emplace_back conforming implementation will forward arguments to the vector<Object>::value_typeconstructor when added to the vector. I recall Visual Studio didn't support variadic templates, but with variadic templates will be supported in Visual Studio 2013 RC, so I guess a conforming signature will be added.

With emplace_back, if you forward the arguments directly to vector<Object>::value_type constructor, you don't need a type to be movable or copyable for emplace_back function, strictly speaking. In the vector<NonCopyableNonMovableObject> case, this is not useful, since vector<Object>::value_type needs a copyable or movable type to grow.

But note that this could be useful for std::map<Key, NonCopyableNonMovableObject>, since once you allocate an entry in the map, it doesn't need to be moved or copied ever anymore, unlike with vector, meaning that you can use std::map effectively with a mapped type that is neither copyable nor movable.


A nice code for the push_back and emplace_back is shown here.

http://en.cppreference.com/w/cpp/container/vector/emplace_back

You can see the move operation on push_back and not on emplace_back.


One more in case of lists:

// constructs the elements in place.                                                
emplace_back("element");


//It will create new object and then copy(or move) its value of arguments.
push_back(explicitDataType{"element"});

참고URL : https://stackoverflow.com/questions/4303513/push-back-vs-emplace-back

반응형