Copy-Ctor optimierung
-
Hallo allerseits!
Hat jemand von euch getestet ob z.B. vektor.push_back(objekt) in vektor.push_back(&objekt) von modernen compilern optimiert werden kann, wenn z.B. nur der default Copy-Ctor verwendet wird?
Danke für die Information!
-
Hallo alteKartoffel,
Die Signatur der Methode heißt:
void push_back( const T& obj );
Folglich wird als Übergabeparameter noch keine Kopie erstellt.
Natürlich kann der Compiler als Eintrag nicht einfach einen Zeiger
von dem Objekt speichern, da es sich auf dem Stack befinden könnte
oder gelöscht werden könnte bevor es nicht mehr im Vector gebraucht
wird.
Folglich kommt der Compiler an dieser Stelle nicht an einem Copy-Construktor-Aufruf vorbei. (Jedenfalls wüsste ich nicht wie und halte es für ausgeschlossen)
Ob jetzt explizit ein Konstruktor definiert wurde, macht an dieser Stelle ja
keinen Unterschied, da du ja keine Garantie für die Lebensdauer des Objektes
hast.Gruß,
CSpille
-
Bei der Uebergabe an push_back gibts keine Kopie, wie CStoll schon sagt. in push_back selber wird aber auf jeden Fall eine Kopie erzeugt, da das Objekt, wo auch immer das Original war, ja in den vom vector<> verwalteten Speicher kopiert werden muss, vermutlich per placement-new und copy-Ctor. Nehmen wir mal an, es wuerde in rigendeiner Implementation keine Kopie gemacht (was schon wegen dem Speichermodell von vwector<> nicht moeglich ist), dann zeigft folgendes beispiel wie grausam das waere:
class A {/*...*/}; int main() { std::vector<A> avec; for (int i = 0; i < 10; ++i) { A atmp; avec.push_back(atmp); } //hier wird atmp zerstoert! // 1) }
Da im vector keine Kopien von atmp abgelegt wurden, beinhaltet der vector jetzt 10 Leichen (kaputte Referenzen, Pointer ins Nirvana oder was auch immer)
Fazit: eine Kopie gibts immer und muss es immer geben.
-
Ich meine natürlich am Beispiel ob ein Compiler das intern erledigen könnte und alle entsprechenden Abhängigkeiten handhabt.
-
Default-Copy-Ctor = elementweises Kopieren. Sprich, fuer jedes Element wird wiederum dessen Copy-Cotr aufgerufen. Wenn deine Klasse (bwz. deren Unterklassen) nur aus PODs bestehen, dann bedeutet der Default-Copy-Ctor also das stumpfe Kopieren von PODs von einem speicher in den anderen. besonders viel zu optimieren gibts da nicht.
Was du mit den "entsprechenden Abhaengigkeiten" meinst und was fuer dich beim Compiler "intern" bedeutet (was waere denn extern?), kann ich nicht ganz nachvollziehn.
-
ich meine z.B.:
#include <vector> #include ... static std::vector<meinTyp> vektor; void ErstelleDaten() { for(int i=0; i<2000; i++) { vektor.push_back(meinTyp(i)); } } ...
oder z.B.:
// x.cpp #include <vector> #include ... static std::vector<meinTyp> vektor; void AddElement(meinTyp& element) { vektor.push_back(element); } ... // y.cpp #include ... void MacheWas() { meinTyp elemente[30]; for(int i=0; i<30; i++) { ... AddElement(elemente[i]); } }
-
Bei Beispiel 1 wird ein temporaeres Element auf dem Stack angelegt und an push_back uebergeben, was im Endeffekt dazu fuehrt, dass der vector eine Kopie auf dem free store oder heap anlegt in dem von ihm verwalteten Speicher. Ob der Compiler das wegoptimieren kann und gleich ein meinTyp(i) auf dem free store draus macht, weiss ich nicht, gehe ich aber nicht von aus.
Beispiel 2 ist nicht grossartig zu optimieren. in AddElement() ist "element" nur eine Referenz auf elemente[i], und das uebergibst du wiederum an die Referenz in push_back(). Am Ende wird push_back() diese Referenz auf elemente[i] an den Copy-Ctor uebergeben, weshalb das Objekt im free store direkt con elemente[i] kopiert wird, ohne wegoptimierbare Zwischeninstanzen.
-
Cool...
Man hält mich schon für so kompetent wie CStoll ^^
Wie gesagt:
Der Compiler analysiert mit Sicherheit nicht, ob die Lebenszeit des Objektes
größer ist als die Aufbewahrung im Vektor.
Dazu müsste er ja die komplette Programmlogik analysieren. -> UtopischIm 1. Beispiel ist das Objekt zwar (mit ziemlicher Sicherheit außer static) auf dem Stack, muss aber beim nächsten Vektor-Aufruf nicht mehr vorhanden sein.
Zu Beispiel 2:
Nach Verlassen von MacheWas ist dein Objekt ja schon zerstört und folglich
hättest du nen Dangling Pointer (Zeiger auf einen freigegebenen Speicherbereich)Gruß,
CSpille
-
CSpille schrieb:
Man hält mich schon für so kompetent wie CStoll ^^
Nein, man liest nur einen Namen der mit CS anfaengt und kriegt aus dem Augenwinkel noch die ll mit => alles klar, das muss CStoll sein Hab draus gelernt und werd demnaechst genauer hinschaun