Frage zu placement new und bitwise Copy



  • Ist folgender Code legal?

    std::aligned_storage_t<sizeof(T), alignof(T)> a, b;
    ::new(static_cast<void*>(a)) T; // erzeuge Objekt in a
    b = a; // kopiere die Bits von T nach a, a wird danach nicht mehr verwendet
    reinterpret_cast<T*>(&b)->~T(); // zerstöre Objekt in b
    // zerstöre Objekt nicht in a
    

    Logisch gesehen, sollte dieser Code legal sein. Man macht zwar keine tiefe Kopie, es wird aber nur ein Objekt zerstört und der Ursprungsspeicher nicht mehr angefasst, weswegen das egal sein sollte.
    Mein Gefühl sagt mir aber, dass das UB sein könnte. Ich konnte das jetzt auch nicht im Standard herausfinden.
    Die Lifetime von T beginnt beim placement new, klar. Die Frage ist nur, ob es definiert ist, den Speicher für das Objekt zu verschieben.


  • Mod

    Ist definiert solange T trivial kopierbar ist. Damit wird auch nicht der Speicher verschoben sondern kopiert, du hast dann also zwei Objekte.



  • Arcoth schrieb:

    Ist definiert solange T trivial kopierbar ist.

    Das war mir klar.
    Und wenns nicht ist? Rein theoretisch sollte das dem T doch egal sein, dass es nun in b ist, anstatt in a.


  • Mod

    Der Edit kam etwas spät.

    Nathan schrieb:

    Und wenns nicht ist?

    Dann ist es Unsinn? Was wenn der Konstruktor this speichert, bpsw. in einer statischen Map? Das zerstört doch nur die Programmlogik. Auch theoretisch.

    Wofür brauchst du das überhaupt? Willst du dir den Move-Konstruktor sparen und gleich zum bitwise copy übergehen? 😃



  • Arcoth schrieb:

    Der Edit kam etwas spät.

    Nathan schrieb:

    Und wenns nicht ist?

    Dann ist es Unsinn? Was wenn der Konstruktor this speichert, bpsw. in einer statischen Map? Das zerstört doch nur die Programmlogik. Auch theoretisch.

    Wer macht denn bitte sowas?

    Wofür brauchst du das überhaupt? Willst du dir den Move-Konstruktor sparen und gleich zum bitwise copy übergehen? 😃

    Implementierung von variant für exception safety.
    Genau genommen assign. Das alte Objekt muss zerstört werden und das neue erstellt. Wenn move nicht throwed kann man einfach ein Dummy Neu erstellen, das alte zerstören und das dummy in den Speicher moven. Aber wenn move throwed gibt es sonst keine schöne Lösung für strong exception safety. Boosts Implementierung erstellt dann da ein default-constructed Fallback Objekt nach einem try-catch, das ist aber auch nicht schön...


  • Mod

    Nathan schrieb:

    Arcoth schrieb:

    Der Edit kam etwas spät.

    Nathan schrieb:

    Und wenns nicht ist?

    Dann ist es Unsinn? Was wenn der Konstruktor this speichert, bpsw. in einer statischen Map? Das zerstört doch nur die Programmlogik. Auch theoretisch.

    Wer macht denn bitte sowas?

    Klassen, die nicht trivial kopierbar sind. Konkret die Speicherung des this in einer statischen Map könnte bei virtuellen Membern erfolgen.


  • Mod

    Ich konnte das jetzt auch nicht im Standard herausfinden.

    Natürlich nicht. Es ist ja auch nicht definiert. Das heißt, es steht nirgends dass es UB ist - es steht aber auch nirgends, dass und wie es definiert ist. Also nicht vom Standard definiert.

    Wer macht denn bitte sowas?

    Darum geht es gar nicht direkt. (SeppJ hat es aber schon zusammengefasst)
    Eine Memberfunktion (wie einen Destruktor) auf ein nicht existierendes Objekt anzuwenden erzeugt undefiniertes Verhalten. Und wenn du ein nicht trivial kopierbares Objekt so "kopierst", bzw. "movest", erzeugst du dabei kein neues Objekt oder verschiebst ein bestehendes. Das alte bleibt wo es ist. Mann kann die Abstraktionsmechanismen nicht immer mit low-level Gefummel vermischen, da steigt der Standard schnell aus und du musst unportable Sachen machen.



  • Ja, ich sehe das mittlerweile auch ein.



  • Muss ja nichtmal ne statische Map sein.
    Reicht doch schon wenn das Objekt sich im Ctor irgendwo als Listener dranhängt und im Dtor wieder entfernt.
    Oder 100 andere Dinge die man mit this anfangen kann.


Log in to reply