2013-05-07 6 views
32

Ich habe einen Code, wo ich routinemäßig einen Vektor mit zwischen 0 und 5000 Elementen fülle. Ich weiß, dass das Maximum überschreitet nie 5000. Stattdessen Vektor mehrere Male von der Initialisierung, ich möchte nur einmalC++ schnellste Möglichkeit, einen Vektor zu löschen oder zu löschen

vector<struct> myvector; 
myvector.reserve(5000); 

jedoch tun, um den Vektor wieder zu füllen, habe ich zuerst den Vektor löschen, ohne seine Fähigkeit zu verändern. Normalerweise rufe ich myvector.clear() auf;

Dies ist eine O (n) -Operation. Gibt es etwas Einfaches, das ich tun kann, um die Leistung zu erhöhen, oder ist es das Beste, was es bekommen wird?

+2

Wird den vorhandenen Elementen eine vernünftige Lösung zugewiesen? –

+0

Nein, weil ich vielleicht 5000 Elemente beim ersten Mal und 3500 beim nächsten Mal hätte, und am Ende wären 1500 alte Elemente übrig ... – user788171

+0

Ist die "Zerstörung" von Elementen ein Problem? –

Antwort

38

Wenn Ihre Struktur einen nicht-trivialen Destruktor hat, dann muss dieser für alle Elemente des Vektors aufgerufen werden, unabhängig davon, wie er geleert wird. Wenn Ihre Struktur nur einen trivialen Destruktor hat, kann der Compiler oder die Implementierung der Standardbibliothek den Zerstörungsprozess optimieren und Ihnen eine O (1) -Operation geben.

+0

Es gibt einen Unterschied zwischen * "der Compiler wird wahrscheinlich optimieren ..." * und * "die Umsetzung kann optimieren Sie die Kosten weg ... "* (wie @ DavidRodríguez-Dribeas in seiner Antwort sagte). Letzteres klingt für mich vernünftiger! – Nawaz

+0

@Nawaz: Ich nehme an, das ist wahr. Meine Absicht war etwas in der Art von "die meisten Compiler führen diese Optimierung durch, so dass Sie wahrscheinlich einen dieser Compiler verwenden", aber ich kann sehen, wie es interpretiert werden kann "manchmal wird der Compiler und manchmal der Compiler nicht optimieren dies, aber normalerweise wird es ". –

+0

Ich denke du hast meinen Kommentar nicht verstanden. Die Aussage * "Die Implementierung kann die Kosten optimieren ..." * ist ein Super-Set, da es neben der Möglichkeit des "optimierten" Bibliothekscodes auch die Idee * "Der Compiler wird wahrscheinlich optimieren" * beinhaltet. Bedeutet, selbst wenn der Compiler selbst die Optimierung nicht durchführt, könnte die Bibliothek so geschrieben werden, dass sie 'O (1)' Code ausgibt, wenn der 'value_type' einen trivialen Destruktor hat (was @ DavidRodríguez-dribeas auch bedeutet, siehe seine Kommentare). – Nawaz

10

Alles, was Sie tun, um die vorhandenen Elemente aus dem Vektor zu entfernen, muss (möglicherweise) den Destruktor jedes zu zerstörenden Elements aufrufen. Aus Sicht des Containers ist daher die lineare Komplexität das Beste, worauf Sie hoffen können.

Das lässt nur die Frage, welche Art von Elementen Sie in dem Vektor speichern. Wenn Sie etwas wie int speichern, von dem der Compiler im Voraus wissen kann/wird, dass es keinen Destruktor zum Aufrufen gibt, sind die Chancen zumindest ziemlich gut, dass die Entfernung mit konstanter Komplexität endet.

Ich bezweifle jedoch, dass die Änderung der Syntax (z. B. clear() vs. resize() vs. erase(begin(), end())) keinen signifikanten Unterschied machen wird. Die Syntax ändert diese Tatsache nicht, die (in Abwesenheit von Threading) N-Destruktoren aufrufen ist eine O (N) -Operation.

23

Die Kosten von clear() hängen hauptsächlich davon ab, was die gespeicherten Objekte sind und insbesondere, ob sie einen trivialen Destruktor haben. Wenn der Typ keinen trivialen Destruktor hat, dann muss der Aufruf alle gespeicherten Objekte zerstören und es ist tatsächlich eine Operation O (n), aber Sie können wirklich nichts Besseres tun.

Nun, wenn die gespeicherten Elemente triviale Destruktoren haben, dann kann die Implementierung die Kosten weg optimieren und clear() wird eine billige O (1) Operation (nur die Größe zurücksetzen - end Zeiger).

Denken Sie daran, dass Sie, um asymptotische Komplexität zu verstehen, wissen müssen, worüber es spricht. Im Fall von clear() stellt es die Anzahl der Destruktoren genannt, aber wenn die Kosten (versteckt) 0 ist, dann ist die Operation ein No-Op.

+0

Können Sie klären, was mit trivialem Destruktor gemeint ist? Ich bin mit dieser Terminologie nicht vertraut. – user788171

+8

Ich denke in diesem Zusammenhang ist "trivial destructor" das gleiche wie "no destructor". –

+4

@ user788171: Vielleicht möchten Sie lesen [Was sind Aggregate und PODs und wie/warum sind sie besonders?] (Http://stackoverflow.com/a/7189821/2070725), um zu verstehen, was diese ganze "triviale" Zeug ist ungefähr (scrolle ein wenig runter, um den "trivialen" Teil zu erreichen). – syam