2017-12-03 3 views
1

Ich habe festgestellt, dass jedes Mal, wenn ich ein Objekt in einen Vektor push_back(), alle vorhandenen Objekte im Vektor "neu erstellt" werden.Erstellt ein Vektor alle Objekte auf einem Push_back() neu?

Um dies zu testen, habe ich das folgende Testprogramm unten gemacht. Was das Programm macht, ist, einige Instanzen von MyClass in einen Vektor zu push_back() und die Adressen der aktuellen Objekte in dem Vektor nach jedem push_back() zu drucken. Der Konstruktor und der Destruktor geben immer dann eine Nachricht mit der Adresse des Objekts aus, wenn eine Instanz erstellt/zerstört wird.

Unten ist die Ausgabe, die ich vom Laufen des Programms bekommen habe. Jeder Block ist die Ausgabe von einer Iteration der Schleife.

Constructor: 00EFF6AF 
Destructor: 00EFF6AF 
Contains objects: 
034425A8 

Constructor: 00EFF6AF 
Destructor: 034425A8 
Destructor: 00EFF6AF 
Contains objects: 
034426F8 
034426F9 

Constructor: 00EFF6AF 
Destructor: 034426F8 
Destructor: 034426F9 
Destructor: 00EFF6AF 
Contains objects: 
034424E8 
034424E9 
034424EA 

Constructor: 00EFF6AF 
Destructor: 034424E8 
Destructor: 034424E9 
Destructor: 034424EA 
Destructor: 00EFF6AF 
Contains objects: 
034423F8 
034423F9 
034423FA 
034423FB 

Appart aus dem Konstruktor und Destruktor des Elements, das als Argument für die push_back(), Destruktoren anderer Objekte gegeben werden während eines push_back() (aber keine entsprechenden Konstrukteuren?) Genannt. Wenn wir uns die Adressen genauer ansehen, sehen wir, dass die Destruktoren zu Elementen im Vektor vor push_back() gehören. Danach enthält der Vektor andere Objekte mit verschiedenen Adressen, aber die gleiche Anzahl von Elementen (plus die neu push_backed).

Was mir dies alles sagt ist, dass alle Objekte im Vektor zerstört und nach jedem Pushback neu erstellt werden. Wenn das der Fall ist, warum ist das? Es scheint wirklich ineffizient, wenn ein Vektor zu groß wird. Wenn es nicht der Fall ist, was passiert genau dann? ?

+4

Suchen Sie nach Kapazität und Reserve. –

+0

Vektoren bieten amortisierte konstante Einfügezeit, also nein, es wird oft nicht wirklich ineffizient bei großen Größen. Es ist nicht in Ordnung für alle, aber es ist in Ordnung für den allgemeinen Gebrauch. – chris

+1

Sie sollten auch den Verschiebungskonstruktor 'MyClass (MyClass &&) noexcept;' und/oder den Kopierkonstruktor 'MyClass (const MyClass &);' instrumentieren, um zu sehen, was wirklich passiert - diese werden verwendet, um die Vektorelemente zu erstellen, weshalb Sie Der Standardkonstruktor wird nicht für sie aufgerufen. Dies sollte nicht immer bei größeren Werten geschehen, aber Ihr Limit ist möglicherweise zu klein, um dies zu beobachten. – aschepler

Antwort

0

Vektor weist etwas Speicherplatz vor.

Zum Beispiel kann es eine anfängliche Größe von 2 Elementen haben. Wenn Sie versuchen, den dritten zu schieben, wird er für 4 Elemente neu zugewiesen. Wenn Sie versuchen, das fünfte Element zu verschieben, wird es für 8 Elemente usw. neu zugewiesen.

Deshalb haben Sie eine .size(), die angibt, wie viele Elemente Sie haben und eine .capacity(), die angibt, wie groß die Kapazität ist (wie viele Elemente können gespeichert werden, bevor eine Neuzuweisung erforderlich ist). Sie können diese Kapazität manuell verarbeiten, indem Sie .reserve() aufrufen

Um Ihre ursprüngliche Frage zu beantworten, erfordert die Neuzuweisung das Kopieren aller Elemente aus dem vorherigen Array in ein größeres. Dies erfordert, die vorherigen Elemente zu zerstören und einige neue zu erstellen. Wenn Sie die Destruktoren Anrufe aber nicht die passende Konstruktoraufrufe gesehen, ist dies, weil es nicht das Standard-Konstruktor verwendet, sondern der Kopierkonstruktor:

MyClass(const MyClass&) 

Dieser Konstruktor nimmt ein Objekt einen Parameter hat und verwendet sie zu konstruieren und initialisiere ein neues Objekt.

Darüber hinaus, wie in den Kommentaren erwähnt: obwohl die Neuzuweisung/Kopie Prozess kann als teuer angesehen werden, ist es im Durchschnitt nicht und tatsächlich bildet eine konstante Zeit Operation. Dies liegt daran, dass die Kosten für die Neuzuweisung und das Kopieren amortisiert sind und sich später einfügen, da wir nicht genau den benötigten Speicherplatz, sondern mehr Speicherplatz als nötig reservieren.

Verwandte Themen