vectors example español ejemplo c++ stl stdvector

example - vector of vectors c++



¿Está std:: vector copiando los objetos con push_back? (8)

¿Por qué fue necesario investigar mucho para descubrirlo? Pruébelo usted mismo con un código simple, por ejemplo

std::vector<std::string> vec; { std::string obj("hello world"); vec.push_pack(obj); } std::cout << vec[0] << std::endl;

Si se imprime "hello world", el objeto debe haber sido copiado

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 push_back.

¿Es eso realmente cierto? Un vector no puede mantener una referencia o un puntero de un objeto sin una copia?

Gracias


A partir de C ++ 11, todos los contenedores estándar ( std::vector , std::map , etc.) admiten la semántica de movimiento, lo que significa que ahora puede pasar valores a contenedores estándar y evitar una copia:

// Example object class. class object { private: int m_val1; std::string m_val2; public: // Constructor for object class. object(int val1, std::string &&val2) : m_val1(val1), m_val2(std::move(val2)) { } }; std::vector<object> myList; // #1 Copy into the vector. object foo1(1, "foo"); myList.push_back(foo1); // #2 Move into the vector (no copy). object foo2(1024, "bar"); myList.push_back(std::move(foo2)); // #3 Move temporary into vector (no copy). myList.push_back(object(453, "baz")); // #4 Create instance of object directly inside the vector (no copy, no move). myList.emplace_back(453, "qux");

Alternativamente, puede usar varios punteros inteligentes para obtener el mismo efecto:

std::unique_ptr example

std::vector<std::unique_ptr<object>> myPtrList; // #5a unique_ptr can only ever be moved. auto pFoo = std::make_unique<object>(1, "foo"); myPtrList.push_back(std::move(pFoo)); // #5b unique_ptr can only ever be moved. myPtrList.push_back(std::make_unique<object>(1, "foo"));

std::shared_ptr example

std::vector<std::shared_ptr<object>> objectPtrList2; // #6 shared_ptr can be used to retain a copy of the pointer and update both the vector // value and the local copy simultaneously. auto pFooShared = std::make_shared<object>(1, "foo"); objectPtrList2.push_back(pFooShared); // Pointer to object stored in the vector, but pFooShared is still valid.


Relevante en C ++ 11 es la familia de funciones integradas, que le permiten transferir la propiedad de los objetos moviéndolos a contenedores.

El modismo de uso se vería como

std::vector<Object> objs; Object l_value_obj { /* initialize */ }; // use object here... objs.emplace_back(std::move(l_value_obj));

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.


Sí, std::vector<T>::push_back() crea una copia del argumento y lo almacena en el vector. Si desea almacenar punteros a objetos en su vector, cree un std::vector<whatever*> lugar de std::vector<whatever> .

Sin embargo, debe asegurarse de que los objetos a los que hacen referencia los punteros sigan siendo válidos, mientras que el vector contiene una referencia a ellos (los punteros inteligentes que utilizan el modismo RAII resuelven el problema).


Sí, std::vector almacena copias. ¿Cómo debe saber el vector 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 encuentra en Boost o TR1 ) para facilitar la administración de recursos.


Std :: vector no solo hace una copia de lo que sea que esté retrocediendo, 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.


si no quieres las copias; entonces la mejor manera es usar un vector de puntero (u otra estructura que sirva para el mismo objetivo). si quieres las copias; use directamente push_back (). no tienes otra opción.


std :: vector siempre hace una copia de lo que se almacena 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 está tratando con objetos grandes, puede (y probablemente debería) usar siempre un vector de punteros. A menudo, utilizar un vector de punteros inteligentes de un tipo apropiado es bueno por motivos de seguridad, ya que manejar la vida útil del objeto y la administración de la memoria puede ser complicado.