So weit wie ich verstehe, wenn stuff pushed_back in einen Vektor ist, muss es manchmal einen neuen Speicherblock zuweisen, was dazu führt, dass alle Elemente aus dem alten Speicherblock hinein kopiert werden und ihre Destruktoren aufgerufen werden. Da unique_ptr-Destruktoren den eigenen Speicher löschen, wie ist es möglich, dass sie mit Vektor arbeiten? Ist es sicher, unique_ptr in Vektoren zu verwenden? Ist es langsamer als normale Zeiger?vector <unique_ptr> resizing mit push_back - wie funktioniert es?
Antwort
was dazu führt, dass alle Elemente aus dem alten Speicherblock in diese kopiert werden und ihre Destruktoren aufgerufen werden. Da unique_ptr-Destruktoren den eigenen Speicher löschen, wie ist es möglich, dass sie mit Vektor arbeiten?
In der Tat, es ist nicht streng Kopieren die Elemente nicht mehr, ist es bewegt. Für Typen, die keinen impliziten oder expliziten Move-Konstruktor haben, ist das gleich. Aber für unique_ptr
s bedeutet das, dass neue unique_ptr
s in dem neu zugewiesenen Speicher konstruiert werden, wobei ein rvalue-Verweis auf das "alte" unique_ptr
s gegeben wird. Ihr Move-Konstruktor macht das Richtige, d. H. Er überträgt das Eigentum von dem alten auf das neue unique_ptr
s, wobei die alten leer gelassen werden, so dass nichts gelöscht wird, wenn sie zerstört werden.
Ist es sicher, unique_ptr in Vektoren zu verwenden?
Es ist sparen unique_ptr
s verwenden überall, so lange wie Sie Sprachregeln respektieren und "C++ common sense". Das heißt, Sie müssen explizit dumme Dinge zu brechen unique_ptr
s sicheres Verhalten. Unter diesen sind z.B.
unique_ptr<T> ptr1 {new T()};
unique_ptr<T> ptr2 {ptr1.get()}; //two unique_ptr's owning the same object...
oder einige destruktiven Handlungen beteiligt reinterpret_cast
, memcpy
, memset
oder andere Dinge, die nicht respektieren Objekt Lebensdauer ++ C: zu geben, das Eigentum an dem Objekt im Besitz einer weiteren intelligenten Zeiger vorgibt.
Ist es langsamer als normale Zeiger?
Vielleicht. Beim Verschieben eines unique_ptr
im Vergleich zum Kopieren eines rohen Zeigers, nämlich dem Setzen des Originals auf Null, ist offensichtlich ein kleiner Aufwand verbunden. Aber ob dieser Overhead optimiert werden kann oder nicht, hängt von Ihrem Compiler und Optimierer ab.Und wie immer mit Leistung, konsultieren Sie Ihren Profiler, um zu beurteilen, ob langsamer ist und ob die Verlangsamung von Bedeutung ist. Ich wette, es wird nicht, und unter Berücksichtigung der Menge an Sicherheit, die die intelligenten Zeiger Ihnen geben werden, fragen Sie nie nach unique_ptr
's Leistung.
Hinweis: Wenn Sie die Größe Ihres Vektors im Voraus kennen, denken Sie daran, vector::reserve()
zu verwenden. Es speichert Sie die Umverteilungen und Bewegungen der unique_ptr
s. Und wenn Sie nur die ungefähre Größe wissen, die Ihr Vektor haben wird, seien Sie nicht kleinlich - unique_ptr
s sind nicht sehr groß (normalerweise so groß wie ein roher Zeiger plus der Deleter, der möglicherweise weg optimiert wird), also reserviert a Wenige Prozent mehr werden nicht weh tun, es sei denn, Sie haben wirklich enge Speicherbeschränkungen.
Nach cppreference ist einer der Anwendungsfälle für std::unique_ptr
Verwendung in "Move-Aware-Container" wie std::vector
. Dies bedeutet, dass std::vector<T>
intelligent genug ist, um zu erkennen, wenn T
beweglich ist, was für std::unique_ptr
der Fall ist, und den Move-Konstruktor zu verwenden, wenn die Größe des Vektors geändert wird.
Nun mit Umzug Semantik ist es möglich, eine unique_ptr von einem Ort zu einem anderen zu verschieben. Dies vermeidet die Zerstörung der Daten, die der Zeiger enthält, wenn er mit std::move
von einem Speicherort zu einem anderen "verschoben" wird.
Es ist eine Art, flache Kopien vom alten Vektor-Array an den neuen Speicherort durchzuführen, wenn der Vektor wächst.
@RandyGual AfterAutle auto_ptr <> unterstützen auch sementic, überträgt es die Verantwortung des Objekts auf das neue Objekt. Also sollte auto_ptr <> auch in diesem Sinne sicher sein. Aber ich glaube das ist nicht der Fall? – David
- 1. push_back Ausgabe std :: vector
- 2. Two Dimensional Vector push_back
- 3. std :: vector <std :: vector <int>> push_back gibt Heap-Pufferüberlauf
- 4. std :: vector bad_alloc ohne push_back
- 5. VC++ vector :: push_back "Zugriffsverletzung" in DLL
- 6. C++ neugierig Verhalten in vector :: push_back()
- 7. mit push_back, um einen Vektor <double> in einen Vektor <vector <double>>
- 8. Ist std :: vector Kopieren der Objekte mit einem Push_back?
- 9. keine übereinstimmende Funktion für den Aufruf von std :: vector <std::tuple> push_back
- 10. Wie mit Doppel * Zeiger verwenden push_back
- 11. Wie std :: vector <std :: reference_wrapper <T>> konvertieren std :: vector <T>
- 12. keine passende Funktion für Aufruf von ‚merge (std :: vector <int> & std :: vector <int> &)
- 13. Mit <vector> mit cin und für() Schleife C++
- 14. Verwendet std :: vector den Zuweisungsoperator seines Werttyps zu push_back-Elementen?
- 15. C++ Problem mit Vektor push_back
- 16. Größenänderung versus push_back in std :: vector: vermeidet es eine unnötige Kopierzuweisung?
- 17. wie eine Matrix in einen Vektor einzufügen <vector<char>>
- 18. emplace_back arbeitet nicht mit std :: vector <std :: map <int, int>>
- 19. Vektor der Vektoren push_back
- 20. Enormes std :: vector <std::vector> gibt nicht alle Speicher auf Zerstörung frei
- 21. Merge vector und initializer_list bei der Initialisierung des Vektors <vector<T>>?
- 22. Qt QTableWidget Spalte resizing
- 23. Resizing div auf Hover
- 24. Was ist Druck << EOF; und wie funktioniert es?
- 25. Vektor __mm128 wird push_back nicht()
- 26. std Vektor Lösch- und push_back
- 27. C++ mit Strukturen als Daten für eine <map, <map, vector>>
- 28. Was zwischen tun Vektor <vector<T...> der Unterschied> und Vektor <vector<T> ...>
- 29. C++ 11-Vektor push_back mehrdeutig
- 30. Wie push_back etwas in einem 2D-Vektor
* so wird das Reservieren von hundert mehr nicht schaden, es sei denn, Sie haben wirklich enge Speicherbeschränkungen. * => Nun, da Container für ein Dutzend oder so Elemente am häufigsten verwendet werden, würde ich es bevorzugen, eine Faustregel als Prozentsatz anzugeben ; wie 10% mehr. –
@MatthieuM. Danke für die Rückmeldung, ich habe diesen Teil neu formuliert. –
@Arne: Wenn wir unique_ptr <> in Vektor <> Container verwenden können, warum nicht auto_ptr <>? Afterall auto_ptr <> verschiebt auch die Verantwortung des Objekts auf das neue Objekt. Also sollte auto_ptr <> auch in diesem Sinne sicher sein. Aber ich glaube das ist nicht der Fall? – David