C ++ 11 emplace_back()
에서는 일반적으로 push_back()
내부 생성을 허용하므로 효율성 측면에서 선호 되지만 push_back(std::move())
이미 생성 된 객체와 함께 사용하는 경우에도 마찬가지 입니까?
예를 들어, emplace_back()
다음과 같은 경우에 여전히 선호됩니까?
std::string mystring("hello world");
std::vector<std::string> myvector;
myvector.emplace_back(mystring);
myvector.push_back(std::move(mystring));
// (of course assuming we don't care about using the value of mystring after)
또한 위의 예에서 대신 다음을 수행하는 이점이 있습니까?
myvector.emplace_back(std::move(mystring));
아니면 여기의 이동이 완전히 중복됩니까, 아니면 효과가 없습니까?
답변
제공 한 다른 호출이 수행하는 작업을 살펴 보겠습니다.
-
emplace_back(mystring)
: 이것은 당신이 제공 한 인수와 함께 새로운 요소의 내부 구조입니다. lvalue를 제공 했으므로 실제로 그 내부 생성은 복사 생성입니다. 즉 이것은 호출과 동일합니다.push_back(mystring)
-
push_back(std::move(mystring))
: 이것은 이동-삽입을 호출하는데,이 경우std::string
내부 이동 구조입니다. -
emplace_back(std::move(mystring))
: 이것은 다시 당신이 제공 한 인수를 가진 내부 구조입니다. 이 인수는 rvalue이므로의 이동 생성자를 호출합니다std::string
. 즉, 2에서와 같은 내부 이동 생성입니다.
즉, 타입 T의 하나 개의 인자로 호출하면,에게를 rvalue 또는 좌변을 수 emplace_back
와 push_back
동일합니다.
그러나 다른 인수의 emplace_back
경우 경주에서 이깁니다. 예를 들어 a char const*
in a vector<string>
:
-
emplace_back("foo")
호출std::string(char const*)
현재 위치에서 – 건설. -
push_back("foo")
먼저std::string(char const*)
함수의 서명과 일치하는 데 필요한 암시 적 변환 을 호출 한 다음 위의 사례 2와 같은 이동 삽입 을 호출 해야합니다. 따라서 다음과 같습니다.push_back(string("foo"))
답변
emplace_back은 rvalue 참조 목록을 가져오고 컨테이너 요소를 제자리에 직접 구성하려고합니다. 컨테이너 요소 생성자가 지원하는 모든 유형으로 emplace_back을 호출 할 수 있습니다. rvalue 참조가 아닌 매개 변수에 대해 emplace_back을 호출하면 일반 참조로 ‘대체’되고 매개 변수와 컨테이너 요소가 동일한 유형일 때 적어도 복사 생성자가 호출되지 않습니다. 귀하의 경우 ‘myvector.emplace_back (mystring)’은 컴파일러가 myvector 매개 변수가 움직일 수 있음을 알 수 없기 때문에 문자열의 사본을 만들어야합니다. 따라서 원하는 이점을 제공하는 std :: move를 삽입하십시오. push_back은 이미 구성된 요소에 대해 emplace_back과 마찬가지로 작동해야합니다.