7

Hier ist eine sehr einfache Art und Weise bewegen Zuordnung für die meisten jede Klasse mit einem Umzug Konstruktor zu definieren:Ist Zugzuweisung über destruct + move construct safe?

class Foo { 
public: 
    Foo(Foo&& foo);      // you still have to write this one 
    Foo& operator=(Foo&& foo) { 
    if (this != &foo) {    // avoid destructing the only copy 
     this->~Foo();     // call your own destructor 
     new (this) Foo(std::move(foo)); // call move constructor via placement new 
    } 
    return *this; 
    } 
    // ... 
}; 

Ist diese Folge von Aufrufen Ihrer eigenen destructor durch Platzierung neu auf dem dieser Zeiger sicher in Standard C++ 11 gefolgt ?

+2

Ihr Move-Konstruktor sollte besser 'noexcept' sein, oder Sie werden versuchen, ein bereits zerstörtes Objekt zu zerstören, wenn es in UB-Land wirft und davonwandert. – ildjarn

+1

Ein guter Trick für verschieben/kopieren Zuordnung ist einfach zu [den Parameter nach Wert annehmen] (http://stackoverflow.com/questions/9746748/does-it-make-sense-to-reuse-destructor-logic-by- using-stdswap-in-a-move-assign/9746772 # 9746772). Ein Benutzer wird entweder den Werteparameter verschieben oder ihn konstruieren (oder in ihn hineinbauen). Sie können dann 'std :: swap' verwenden, um den Wert in Ihr Objekt zu tauschen. –

Antwort

6

Nur wenn Sie nie leiten je einen Typ aus dieser Klasse. Wenn Sie dies tun, wird dies das Objekt in eine Monstrosität verwandeln. Es ist bedauerlich, dass der Standard dies als Beispiel für die Erklärung von Objektlebensdauern verwendet. Es ist wirklich eine schlechte Sache, in realem Code zu tun.

+0

Gibt es auch ein Problem mit neu zugewiesenem Speicher, manuell zu speichern, dann neu zu platzieren? Ich müsste Standard-vertiefen, um zu überprüfen, dass dies selbst erlaubt ist. – Yakk

+0

@Yakk nein, da du nichts zugewiesen hast. –

+0

@Yakk nein, es solle kein Problem in dieser Hinsicht sein, solange das Objekt ursprünglich ausreichende Größe und Ausrichtungsanforderungen zugewiesen hat für das Objekt, das Sie über die Platzierung neu zu erstellen, und der Zeiger Sie ist ein entsprechenden Typ löscht passieren zu. – bames53

0

Technisch ist der Quellcode sicher in diesem winzigen Beispiel. Aber die Realität ist, dass, wenn du Foo jemals komisch ansiehst, du UB anrufen wirst. Es ist so furchtbar unsicher, dass es sich absolut nicht lohnt. Verwenden Sie Swap wie alle anderen auch - es gibt einen Grund dafür, und das liegt daran, dass dies die richtige Wahl ist. Außerdem ist die Selbstzuweisungsprüfung schlecht.

+2

Kopieren und Tauschen ist nicht immer die beste Implementierung. Es ist eine einfache Möglichkeit, die starke Sicherheitsgarantie zu erhalten, aber es gibt Kompromisse. Howard Hinnant bespricht es teilweise in dieser Antwort (http://stackoverflow.com/a/6687520/365496). – bames53

+0

Handelt es sich hauptsächlich um einen abgeleiteten Klassenautor, der (in diesem Fall fälschlicherweise) die Foo-Bewegungsaufgabe aufruft, oder gibt es mehr Probleme? Diese Technik erfordert Unterklassenautoren, virtuell zu überschreiben und die Technik zu verwenden.Die meisten Probleme, die ich mir darüber hinaus vorstellen kann, beinhalten, dass die Bewegungsaufgabe nicht virtuell ist, und dann lautet die Antwort nur, dass die Bewegungszuweisung in diesen Fällen virtuell sein sollte, unabhängig davon, ob diese Technik verwendet wird (stimmst du zu?). Haben Sie darüber hinaus Bedenken? –