이미 구성된 객체에 대한 std :: move 대 emplace_back ()을 사용한 C ++ 11 push_back ()의 ​​효율성


88

C ++ 11 emplace_back()에서는 일반적으로 push_back()내부 생성을 허용하므로 효율성 측면에서 선호 되지만 push_back(std::move())이미 생성 된 객체와 함께 사용하는 경우에도 마찬가지 입니까?

예를 들어, emplace_back()다음과 같은 경우에 여전히 선호됩니까?

또한 위의 예에서 대신 다음을 수행하는 이점이 있습니까?

아니면 여기의 이동이 완전히 중복됩니까, 아니면 효과가 없습니까?


myvector.emplace_back(mystring);복사하고 움직이지 않습니다. 나머지 두 동작은 동일해야합니다.
TC

답변:


117

제공 한 다른 호출이 수행하는 작업을 살펴 ​​보겠습니다.

  1. emplace_back(mystring): 이것은 당신이 제공 한 인수와 함께 새로운 요소의 내부 구조입니다. lvalue를 제공 ​​했으므로 실제로 그 내부 생성은 복사 생성입니다. 즉 이것은 호출과 동일합니다.push_back(mystring)

  2. push_back(std::move(mystring)): 이것은 이동-삽입을 호출하는데,이 경우 std::string내부 이동 구조입니다.

  3. emplace_back(std::move(mystring)): 이것은 다시 당신이 제공 한 인수를 가진 내부 구조입니다. 이 인수는 rvalue이므로의 이동 생성자를 호출합니다 std::string. 즉, 2에서와 같은 내부 이동 생성입니다.

즉, 타입 T의 하나 개의 인자로 호출하면,에게를 rvalue 또는 좌변을 수 emplace_backpush_back동일합니다.

그러나 다른 인수의 emplace_back경우 경주에서 이깁니다. 예를 들어 a char const*in a vector<string>:

  1. emplace_back("foo")호출 std::string(char const*)현재 위치에서 - 건설.

  2. push_back("foo")먼저 std::string(char const*)함수의 서명과 일치하는 데 필요한 암시 적 변환 을 호출 한 다음 위의 사례 2와 같은 이동 삽입 을 호출 해야합니다. 따라서 다음과 같습니다.push_back(string("foo"))


1
이동 생성자는 일반적으로 복사 생성자보다 효율적이므로 동일한 의미에도 불구하고 rvalue (케이스 2, 3)를 사용하는 것이 lvalue (케이스 1)를 사용하는 것보다 효율적입니다.
라이언 리

그런 상황은 어떻습니까? void foo (string && s) {vector.emplace (s); // 1 vector.emplace (std :: move (s)); // 2}
VALOD9

@VALOD는 내 목록의 번호 1과 3입니다. sr- 수치 귀속 만 우변을 참조하지만, 내부로 정의 될 수있다 foo, s좌변이다.
Arne Mertz

1

emplace_back은 rvalue 참조 목록을 가져오고 컨테이너 요소를 제자리에 직접 구성하려고합니다. 컨테이너 요소 생성자가 지원하는 모든 유형으로 emplace_back을 호출 할 수 있습니다. rvalue 참조가 아닌 매개 변수에 대해 emplace_back을 호출하면 일반 참조로 '대체'되고 매개 변수와 컨테이너 요소가 동일한 유형일 때 적어도 복사 생성자가 호출되지 않습니다. 귀하의 경우 'myvector.emplace_back (mystring)'은 컴파일러가 myvector 매개 변수가 움직일 수 있음을 알 수 없기 때문에 문자열의 사본을 만들어야합니다. 따라서 원하는 이점을 제공하는 std :: move를 삽입하십시오. push_back은 이미 구성된 요소에 대해 emplace_back과 마찬가지로 작동해야합니다.


2
그것은 전달 / 유니버설 참조를 설명하는 흥미로운 방법입니다.
TC
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.