태그 보관물: visual-studio-2010

visual-studio-2010

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

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

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

가로 push_back과부하 내가 아주의 목적은 무엇 보지 않는를 rvalue 참조 복용 emplace_back되고 있습니까?



답변

방문자가 말한 것 외에도 :

void emplace_back(Type&& _Val)MSCV10에서 제공하는 기능 은 규격에 맞지 않고 중복되어 있습니다 push_back(Type&& _Val).

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

대신 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 임베드 기능은 현재 일종의 자리 표시 자입니까?

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

variadic 템플릿이 컴파일러에서 구현되면 내장 함수를 포함하여 라이브러리에서 템플릿을 활용할 것으로 기대할 수 있습니다. 우리는 준수를 매우 중요하게 생각하지만 불행히도 모든 것을 한꺼번에 할 수는 없습니다.

이해할 수있는 결정입니다. 전 처리기 끔찍한 요령으로 다양한 템플릿을 에뮬레이션하려고 한 번만 시도한 사람은이 물건이 얼마나 역겨운 지 알고 있습니다.


답변

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다음 예에서 최적화에 대해 설명 할 수 있습니다.

들어 emplace_back생성자 A (int x_arg)호출됩니다. for
push_back A (int x_arg)가 먼저 move A (A &&rhs)호출되고 이후에 호출됩니다.

물론 생성자는로 표시되어야 explicit하지만 현재 예제에서는 명시 성을 제거하는 것이 좋습니다.

#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;
}

산출:

call emplace_back:
A (x_arg)

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

답변

push_back 및 emplace_back에 대한 좋은 코드가 여기에 표시됩니다.

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

emplace_back이 아니라 push_back에서 이동 작업을 볼 수 있습니다.


답변

emplace_back적합한 구현은 vector<Object>::value_type벡터에 추가 될 때 인수를 생성자에 전달 합니다. Visual Studio는 가변 템플릿을 지원하지 않았지만 가변 템플릿을 사용하면 Visual Studio 2013 RC에서 지원되므로 적합한 서명이 추가 될 것입니다.

을 사용 emplace_back하면 인수를 vector<Object>::value_type생성자 에게 직접 전달하면 emplace_back엄밀히 말하면 함수를 위해 이동 가능하거나 복사 가능한 유형이 필요하지 않습니다 . 이 vector<NonCopyableNonMovableObject>경우 vector<Object>::value_type 복사 할 수 있거나 움직일 수있는 유형이 필요 하므로 유용하지 않습니다 .

그러나 참고 이 유용 할 수 있다고 std::map<Key, NonCopyableNonMovableObject>당신은지도에 엔트리를 할당하면, 그것은 이동하거나와는 달리, 더 이상 지금까지 복사 할 필요가 없기 때문에, vector당신이 사용할 수있는 의미 std::map도 복사 가능한입니다 매핑 유형을 효과적으로도 움직일 수 있는.


답변

목록의 경우 하나 더 :

// 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"});

답변

구체적인 사용 사례 emplace_back: 임시 객체를 생성하여 컨테이너로 푸시해야하는 경우 emplace_back대신을 사용하십시오 push_back. 컨테이너 내에서 개체를 제자리에 만듭니다.

노트:

  1. push_back위의 경우 임시 객체를 만들어 컨테이너로 옮깁니다. 그러나 사용되는 내부 구성 emplace_back은 오브젝트를 구성한 다음 이동하는 것 (일반적으로 일부 복사가 필요함)보다 성능이 우수합니다.
  2. 일반적으로, 당신이 사용할 수있는 emplace_back대신에 push_back많은 문제없이 모든 경우에. ( 예외 참조 )