Después de muchas investigaciones con valgrind, he llegado a la conclusión de que std :: vector hace una copia de un objeto que desea hacer retroceder.
¿Es eso realmente cierto? ¿Un vector no puede mantener una referencia o un puntero de un objeto sin una copia?
Gracias

*o¶ hacer un puntero o referencia.push_back: se necesita aconst&. O arroja el valor (inútil), o hay un método de recuperación. Por lo tanto, observamos la firma debacky devuelve simple&, por lo que se copió el valor original oconstse ha descartado silenciosamente (muy mal: comportamiento potencialmente indefinido). Asumiendo que los diseñadores devectoreran racionales (vector<bool>no obstante) concluimos que hace copias.Respuestas:
Sí,
std::vector<T>::push_back()crea una copia del argumento y la almacena en el vector. Si desea almacenar punteros a objetos en su vector, cree un enstd::vector<whatever*>lugar destd::vector<whatever>.Sin embargo, debe asegurarse de que los objetos a los que hacen referencia los punteros siguen siendo válidos mientras el vector tiene una referencia a ellos (los punteros inteligentes que utilizan el lenguaje RAII resuelven el problema).
fuente
push_backrealizará un movimiento en lugar de una copia si el argumento es una referencia de valor. (Los objetos se pueden convertir en referencias de valor constd::move().)emplace_backpara evitar cualquier copia o movimiento (construir el objeto en el lugar proporcionado por el contenedor).Sí,
std::vectoralmacena copias. ¿Cómo debevectorsaber cuáles son los tiempos de vida esperados de sus objetos?Si desea transferir o compartir la propiedad de los objetos, use punteros, posiblemente punteros inteligentes como
shared_ptr(que se encuentran en Boost o TR1 ) para facilitar la administración de recursos.fuente
boost::ptr_vector?class Foo { typedef boost::shared_ptr<Foo> ptr; };para escribirFoo::ptr.shared_ptrno es exactamente disparar y olvidar. Consulte stackoverflow.com/questions/327573 y stackoverflow.com/questions/701456Desde C ++ 11 en adelante, todos los contenedores estándar (
std::vector,std::map, etc) de soporte se mueven semántica, lo que significa que ahora puede pasar a rvalues contenedores estándar y evitar una copia:Alternativamente, puede usar varios punteros inteligentes para obtener el mismo efecto:
std::unique_ptrejemplostd::shared_ptrejemplofuente
std::make_unique(molestamente) está disponible solo en C ++ 14 y superior. Asegúrese de decirle a su compilador que establezca su conformidad estándar en consecuencia si desea compilar estos ejemplos.auto pFoo =para evitar la repetición; y todos losstd::stringmoldes se pueden eliminar (hay una conversión implícita de literales de cadena astd::string)make_uniquese puede implementar fácilmente en C ++ 11, por lo que es solo una ligera molestia para alguien atrapado con un compilador de C ++ 11template<typename T, typename... Args> unique_ptr<T> make_unique(Args&&... args) { return unique_ptr<T>{new T{args...}}; }std::move()constd::shared_ptr, el puntero compartido original podría cambiar su puntero ya que la propiedad se pasó al vector. Ver aquí: coliru.stacked-crooked.com/a/99d4f04f05e5c7f3std :: vector siempre hace una copia de lo que se está almacenando en el vector.
Si mantiene un vector de punteros, hará una copia del puntero, pero no la instancia a la que apunta el puntero. Si se trata de objetos grandes, siempre puede (y probablemente debería) usar un vector de punteros. A menudo, usar un vector de punteros inteligentes de un tipo apropiado es bueno para fines de seguridad, ya que manejar la vida útil de los objetos y la administración de la memoria puede ser complicado de lo contrario.
fuente
Std :: vector no solo hace una copia de lo que está presionando, sino que la definición de la colección establece que lo hará, y que no puede usar objetos sin la semántica de copia correcta dentro de un vector. Entonces, por ejemplo, no usa auto_ptr en un vector.
fuente
Relevante en C ++ 11 es la
emplacefamilia de funciones miembro, que le permiten transferir la propiedad de los objetos moviéndolos a contenedores.El modismo de uso se vería así
El movimiento para el objeto lvalue es importante ya que de lo contrario se reenviaría como referencia o referencia constante y no se llamaría al constructor de movimiento.
fuente
si no quieres las copias; entonces la mejor manera es usar un vector puntero (u otra estructura que sirva para el mismo objetivo). si quieres las copias; usar directamente push_back (). No tienes otra opción.
fuente
¿Por qué tomó tanta investigación valgrind para descubrir esto? Solo demuéstralo a ti mismo con un código simple, por ejemplo
Si se imprime "hello world", el objeto debe haberse copiado
fuente