Impliziter Konstruktoraufruf


  • Mod

    Ben04 schrieb:

    camper schrieb:

    Braunstein schrieb:

    Im genannten Fall sollte der Compiler aber so schlau sein und nur den Konstruktor aufrufen.

    Im besagten Falle, ist es ihm sogar verboten, das zu tun (wenn der Kopiervorgang beobachtbar ist versteht sich).

    Bist du sicher? Soweit ich weiß dürfen Kopiekonstrktor-Aufrüfe ausdrücklich auch sonst weg optimiert werden. Eine solche Sonderreglung gibt es, ob sie allerdings hier zutrifft weiß ich nicht.

    Der Compiler muss natürlich immer noch prüfen ob der Kopiekonstrktor aufgerufen werden könnte allerdings braucht er ihn anschließend nicht aufzurufen.

    es gibt nur zwei Fälle, in denen es erlaubt ist:

    This elision of copy operations is permitted in the following circumstances (which may be combined to eliminate multiple copies):
    — in a return statement in a function with a class return type, when the expression is the name of a non-volatile automatic object with the same cv-unqualified type as the function return type, the copy
    operation can be omitted by constructing the automatic object directly into the function’s return value
    — when a temporary class object that has not been bound to a reference (12.2) would be copied to a class object with the same cv-unqualified type, the copy operation can be omitted by constructing the temporary object directly into the target of the omitted copy

    Wir haben es nicht mit einem return statement zu tun - also trifft der erste Fall nicht zu.
    Der zweite Fall trifft ebenfalls nicht zu, denn unser Objekt wurde (beim Funktionsaufruf) an eine Referenz gebunden. verbleibt nur noch die as-if Regel...



  • camper schrieb:

    Er kopiert elementweise - technisch läuft das auf placement new hinaus, weil es ja keinen Weg gibt (außer in Initialisierungslisten), einen Konstruktor explizit aufzurufen. memcpy & Co. produziert erstens meist undefiniertes Verhalten und würde auch oft das Falsche machen.

    Nur funktioniert das sogar mit Typen die z.B. Arrays beinhalten.
    Wie das?!


  • Mod

    sqrt(-1) schrieb:

    camper schrieb:

    Er kopiert elementweise - technisch läuft das auf placement new hinaus, weil es ja keinen Weg gibt (außer in Initialisierungslisten), einen Konstruktor explizit aufzurufen. memcpy & Co. produziert erstens meist undefiniertes Verhalten und würde auch oft das Falsche machen.

    Nur funktioniert das sogar mit Typen die z.B. Arrays beinhalten.
    Wie das?!

    Weil für das Kopieren des Memberarrays der Kopierkonstruktor des betreffenden Typen, der das Array enthält zuständig ist. Der vector kriegt davon gar nichts mit. Im Gegensatz dazu kann aber ein Array nicht selbst Element eines vector sein.



  • Wie läuft das dann bei einem Array ab?
    Werden dann also alle Elemente einzeln kopiert?



  • Der Standard sagt: "- wenn das Subobjekt ein Feld ist, wird jedes Element so kopiert, wie es passend zum Elementtyp ist;"

    Also wird scheinbar tatsächlich jedes Element einzeln kopiert.
    Ob der Compiler da optimiert? Naja...



  • sqrt(-1) schrieb:

    Ob der Compiler da optimiert? Naja...

    Also Kopierschleifen mit inline Zuweisungsoperatoren sind eigentlich eine Spezialität moderner Compiler 😉



  • Karatekatze schrieb:

    Hallo!

    mal folgendes angenommen:

    vector<Typ> vektor;
    vektor.push_back(Typ());
    

    Was passiert da überhaupt genau?
    ...

    Ich habe das mal selbst durch den Debugger laufen lassen, wobei der Containertyp ein Klassenobjekt ist.
    Nach einem push_back befinden sich dann ZWEI Elemente im Vektor!
    Das Erste wie gewünscht, und das Zweite ist korrupt.

    Also wurde hier das Verhalten scheinbar noch nicht vollends korrekt wiedergegeben, und die Frage nach dem, was denn da genau passiert, bleibt weiter offen.



  • Komischerweise liegt dieses Verhalten nur vor, wenn nicht der standard Ctor benutzt wird.



  • Das Problem liegt in folgenden Fällen vor:

    vector<Typ> vektor;
    vektor.push_back(Typ(parameter));
    
    vector<Typ*> vektor;
    vektor.push_back(new Typ(parameter));
    

    Wieso zum Geier wird hier ein zweites, korruptes Element hinzugefügt?

    Der Code von push_back und allem was dahinter steckt ist viel zu kryptisch geschrieben (was haben die sich gedacht!?), als dass man dies nachvollziehen könnte.



  • Hmm... kann es sein dass _Myend bei einem Container mit einem Elementen nicht definiert ist?



  • off topic

    sqrt(-1) schrieb:

    Wieso zum Geier wird hier ein zweites, korruptes Element hinzugefügt?

    Das englische "corrupt" bedeutet unter anderem auch beschädigt. Kann man das deutsche "korrupt" tatsächlich auch als beschädigt verwenden? Irgendwie klingt das in meinen Ohren falsch.



  • Kommt beides vom gleichem lateinischem Begriff (corrumpere) und hat die gleiche Bedeutung.

    Übrigens ist Größe des Vektors tatsächlich nur eins.
    Nur wird eben unter den genannten Umständen _Mylast und _Myend mit irgend einem zweiten Element belegt.



  • _Mylast und _Myend beginnen mit einem Unterstrich und einem Großbuchstaben. Ihre Verwendung ist ein Privileg des Compilers. Der normale Anwender sollte die Methoden back() und end() verwenden.

    Achja, das zweite Element ist denke ich voralloziert, so dass beim nächsten push_back kein Speicher mehr alloziert werden muss. Ist aber nur eine Vermutung.

    Gruß
    Don06



  • sqrt(-1) schrieb:

    Kommt beides vom gleichem lateinischem Begriff (corrumpere) und hat die gleiche Bedeutung.

    corrumpere = verderben, zerbrechen, entkräften, entstellen, bestechen



  • Oder auf gut deutsch: korrumpieren


Anmelden zum Antworten