2016-09-02 3 views
17

Ich habe versucht, einen Move-Konstruktor für eine Klasse ohne einen Kopierkonstruktor zu implementieren. Ich habe einen Fehler bekommen, dass der Standardkonstruktor für ein Mitglied der Klasse fehlte.Warum benötigt ein Verschiebungskonstruktor einen Standardkonstruktor für seine Mitglieder?

Hier ist ein triviales Beispiel um dies zu verdeutlichen:

struct A { 
public: 
     A() = delete; 
     A(A const&) = delete; 
     A(A &&a) {} 
}; 

struct B { 
     A a; 
     B() = delete; 
     B(B const&) = delete; 
     B(B &&b) {} 
}; 

dies kompilieren Der Versuch, die ich erhalten:

move_without_default.cc: In constructor ‘B::B(B&&)’: 
move_without_default.cc:15:11: error: use of deleted function ‘A::A()’ 
    B(B &&b) {} 
     ^
move_without_default.cc:6:2: note: declared here 
    A() = delete; 
^

Warum ist das ein Fehler? Irgendwie in der Nähe?

+8

Ersetze '{}' mit '= default;' – cpplearner

+0

Weil 'A's Standardkonstruktor gelöscht wird, aber' B' verwendet es. – tkausl

+6

Ein leerer Move-Konstruktor versucht nicht automatisch, eine member-by-member-Verschiebung durchzuführen. Ihr Move-Konstruktor versucht, "a" standardmäßig zu konstruieren, nicht move-construct. – user2357112

Antwort

17

Verwenden Sie die Initialisierungsliste des Konstruktors, um das Element A zu initialisieren. Wie geschrieben, verwendet der Move-Konstruktor, wie der Compiler sagt, den Standardkonstruktor für A.

B(B&& b) : a(std::move(b.a)) {} 
9

Ein Verschiebungskonstruktor muss im Allgemeinen keine Standardinitialisierung bereitstellen. Ihr Move-Konstruktor tut.

Ein Move Constructor ist immer noch ein Konstruktor. Daher müssen alle Unterobjekte initialisiert werden. Wenn Sie keine explizite Initialisierung angeben, wird versucht, sie standardmäßig zu initialisieren. Und wenn es das nicht kann, erhalten Sie einen Fehler.

So können Sie sie entweder initialisieren (vielleicht von b verschieben), oder einfach = default mit Ihrem Move-Konstruktor verwenden und den Compiler seinen Job machen lassen.

23

Warum benötigt ein Verschiebungskonstruktor einen Standardkonstruktor für seine Mitglieder?

Der Umzug Konstruktor , die Sie default-Konstrukte ein Mitglied definiert. Wenn Sie standardmäßig Member erstellen, ist der Standardkonstruktor für diese Member erforderlich.

Ein Konstruktor (sei es regulär, kopieren oder verschieben) initialisiert die Elemente, die nicht in der Elementinitialisierungsliste aufgeführt sind, und hat keine Standardelementinitialisierung. B::a ist nicht in der Member-Initialisierungsliste des Verschiebungskonstruktors (es hat überhaupt keine Initialisierungsliste) und es hat keine Standardelementinitialisierung.

Um es herum?

Am einfachsten verwenden Sie den Standard bewegen Konstruktor:

B(B&&) = default; 

Der Standard bewegen Konstruktor move-Konstrukte, die Mitglieder.

Verwandte Themen