Std :: vector copia gli oggetti con un push_back?

Dopo molte indagini con valgrind, ho concluso che std :: vector fa una copia di un object che vuoi push_back.

È proprio vero? Un vettore non può mantenere un riferimento o un puntatore di un object senza una copia?!

Grazie

Sì, std::vector::push_back() crea una copia dell’argomento e lo memorizza nel vettore. Se vuoi memorizzare puntatori su oggetti nel tuo vettore, crea uno std::vector invece di std::vector .

Tuttavia, è necessario assicurarsi che gli oggetti referenziati dai puntatori rimangano validi mentre il vettore contiene un riferimento a essi (i puntatori intelligenti che utilizzano l’idioma RAII risolvono il problema).

Sì, std::vector memorizza le copie. Come deve il vector sapere quali sono i tempi di vita previsti dei tuoi oggetti?

Se si desidera trasferire o condividere la proprietà degli oggetti, utilizzare puntatori, eventualmente indicatori intelligenti come shared_ptr (trovati in Boost o TR1 ) per facilitare la gestione delle risorse.

A partire da C ++ 11, tutti i contenitori standard ( std::vector , std::map , ecc.) Supportano la semantica del movimento, il che significa che ora puoi passare rvalues ​​ai contenitori standard ed evitare 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 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"); 

In alternativa puoi usare vari puntatori intelligenti per ottenere lo stesso effetto:

std::unique_ptr esempio

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

std::shared_ptr esempio

 std::vector> 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(1, "foo"); objectPtrList2.push_back(pFooShared); // Pointer to object stored in the vector, but pFooShared is still valid. 

std :: vector fa sempre una copia di ciò che viene memorizzato nel vettore.

Se stai mantenendo un vettore di puntatori, allora farà una copia del puntatore, ma non l’istanza a cui punta il puntatore. Se hai a che fare con oggetti di grandi dimensioni, puoi (e probabilmente dovrebbe) usare sempre un vettore di puntatori. Spesso, l’utilizzo di un vettore di puntatori intelligenti di un tipo appropriato è utile per motivi di sicurezza, dal momento che gestire la durata degli oggetti e la gestione della memoria può essere complicato altrimenti.

Std :: vector non solo fa una copia di ciò che stai respingendo, ma la definizione della collezione afferma che lo farà, e che non puoi usare oggetti senza la semantica della copia corretta all’interno di un vettore. Quindi, per esempio, non usi auto_ptr in un vettore.

Rilevante in C ++ 11 è la famiglia emplace di funzioni membro, che consentono di trasferire la proprietà degli oggetti spostandoli in contenitori.

L’idioma di utilizzo sarebbe simile

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

Lo spostamento per l’object lvalue è importante in quanto altrimenti sarebbe inoltrato come riferimento o riferimento const e il costruttore di movimento non verrebbe chiamato.

se non vuoi le copie; allora il modo migliore è usare un vettore puntatore (o un’altra struttura che serve per lo stesso objective). se vuoi le copie; utilizzare direttamente push_back (). non hai altra scelta.

Perché è bastato un sacco di approfondite indagini per scoprirlo! Provalo solo con un semplice codice es

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

Se viene stampato "Hello World", l'object deve essere stato copiato