vectors example c++11 move-semantics push-back emplace

c++11 - example - Eficiencia de C++ 11 push_back() con std:: move versus emplace_back() para objetos ya construidos



vector iterator c++ (2)

En C ++ 11, generalmente se prefiere emplace_back() (en términos de eficiencia) a push_back() ya que permite la construcción en el lugar, pero este es el caso cuando se usa push_back(std::move()) con un ya- objeto construido?

Por ejemplo, emplace_back() todavía se prefiere emplace_back() en casos como el siguiente?

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)

Además, ¿hay algún beneficio en el ejemplo anterior para hacer en su lugar:

myvector.emplace_back(std::move(mystring));

¿O el traslado aquí es completamente redundante o no tiene ningún efecto?


Emplace_back obtiene una lista de referencias rvalue e intenta construir un elemento contenedor directamente en su lugar. Puede llamar a emplace_back con todos los tipos que admiten los constructores de elementos de contenedor. Cuando se llama a emplace_back para parámetros que no son referencias de valor, ''retrocede'' a referencias normales y al menos el constructor de copia se llama cuando el parámetro y los elementos del contenedor son del mismo tipo. En su caso, ''myvector.emplace_back (mystring)'' debe hacer una copia de la cadena porque el compilador no puede saber que el parámetro myvector es móvil. Así que inserta el std :: move lo que te da el beneficio deseado. Push_back debería funcionar tan bien como emplace_back para elementos ya construidos.


Veamos qué hacen las diferentes llamadas que proporcionó:

  1. emplace_back(mystring) : esta es una construcción en el lugar del nuevo elemento con cualquier argumento que haya proporcionado. Dado que proporcionó un valor l, esa construcción en el lugar de hecho es una construcción de copia, es decir, esto es lo mismo que llamar a push_back(mystring)

  2. push_back(std::move(mystring)) : Esto llama a la inserción de movimiento, que en el caso de std :: string es una construcción de movimiento in situ.

  3. emplace_back(std::move(mystring)) : esta es nuevamente una construcción en el lugar con los argumentos que proporcionó. Dado que ese argumento es un valor r, llama al constructor de movimiento de std::string , es decir, es una construcción de movimiento en el lugar como en 2.

En otras palabras, si se llama con un argumento de tipo T, ya sea rvalue o emplace_back , emplace_back y push_back son equivalentes.

Sin embargo, para cualquier otro argumento, emplace_back gana la carrera, por ejemplo con un char const* en un vector<string> :

  1. emplace_back("foo") llama a string::string(char const*) para la construcción en el lugar.

  2. push_back("foo") primero tiene que llamar a string::string(char const*) para la conversión implícita necesaria para que coincida con la firma de la función, y luego una inserción de movimiento como el caso 2. anterior. Por lo tanto, es equivalente a push_back(string("foo"))