Frage

Ich weiß, dass der Compiler manchmal einen Standard Copykonstruktor bietet, wenn Sie sich nicht umsetzen kann. Ich bin verwirrt darüber, was genau dieser Konstruktor tut. Wenn ich eine Klasse, die andere Objekte enthält, von denen keine eine Kopie Konstruktor deklariert, was wird das Verhalten sein? Zum Beispiel kann eine Klasse wie folgt:

class Foo {
  Bar bar;
};

class Bar {
  int i;
  Baz baz;
};

class Baz {
  int j;
};

Nun, wenn ich dies tun:

Foo f1;
Foo f2(f1);

Wie wird der Standard Copykonstruktor tun? Wird der Compiler-generierte Kopierkonstruktor in Foo den Compiler generierte in Bar Konstruktor aufrufen über bar zu kopieren, die dann den Compiler generierte Kopierkonstruktor in Baz nennen?

War es hilfreich?

Lösung

Foo f1;
Foo f2(f1);

Ja, das tun, was Sie es erwarten:
Die f2 Kopierkonstruktor Foo :: Foo (Foo const &) aufgerufen.
Diese Kopie baut seine Basisklasse und dann jedes Element (rekursiv)

Wenn Sie definieren eine Klasse wie folgt:

class X: public Y
{
    private:
        int     m_a;
        char*   m_b;
        Z       m_c;
};

Die folgenden Methoden werden von Ihrem Compiler definiert werden.

  • Constructor (default) (2 Versionen)
  • Constructor (Kopie)
  • Destructor (Standard)
  • Zuweisungsoperator

Constructor: Standard:

Es gibt eigentlich zwei Standardkonstruktoren.
Man ist für zero-initialization verwendet, während die andere für value-initialization verwendet wird. Das verwendete davon abhängig, ob Sie () während der Initialisierung oder nicht.

// Zero-Initialization compiler generated constructor
X::X()
    :Y()                // Calls the base constructor
                        //     If this is compiler generated use 
                        //     the `Zero-Initialization version'
    ,m_a(0)             // Default construction of basic PODS zeros them
    ,m_b(0)             // 
    m_c()               // Calls the default constructor of Z
                        //     If this is compiler generated use 
                        //     the `Zero-Initialization version'
{
}

// Value-Initialization compiler generated constructor
X::X()
    :Y()                // Calls the base constructor
                        //     If this is compiler generated use 
                        //     the `Value-Initialization version'
    //,m_a()            // Default construction of basic PODS does nothing
    //,m_b()            // The values are un-initialized.
    m_c()               // Calls the default constructor of Z
                        //     If this is compiler generated use 
                        //     the `Value-Initialization version'
{
}

Weitere Informationen: Wenn die Basisklasse oder alle Mitglieder eine gültige sichtbar Standardkonstruktor nicht haben, dann können die Standard-Konstruktor nicht erzeugt werden. Dies ist kein Fehler, es sei denn, der Code versucht, den Standard-Konstruktor (dann nur noch ein Kompilierung-Fehler) zu verwenden.

Constructor (Copy)

X::X(X const& copy)
    :Y(copy)            // Calls the base copy constructor
    ,m_a(copy.m_a)      // Calls each members copy constructor
    ,m_b(copy.m_b)
    ,m_c(copy.m_c)
{}

Weiteren Informationen: Wenn die Basisklasse oder alle Mitglieder einen gültigen sichtbar Copykonstruktor nicht hat, dann kann der Copykonstruktor nicht erzeugt werden. Dies ist kein Fehler, es sei denn, Ihr Code versucht, den Copykonstruktor (dann nur noch ein Kompilierung-Fehler) zu verwenden.

Zuordnung Operator

X& operator=(X const& copy)
{
    Y::operator=(copy); // Calls the base assignment operator
    m_a = copy.m_a;     // Calls each members assignment operator
    m_b = copy.m_b;
    m_c = copy.m_c;

    return *this;
}

Weiteren Informationen: Wenn die Basisklasse oder alle Mitglieder einen gültigen tragfähige Zuweisungsoperator nicht hat, dann kann der Zuweisungsoperator nicht generiert werden. Dies ist kein Fehler, es sei denn, der Code versucht, den Zuweisungsoperator (dann nur noch ein Kompilierung-Fehler) zu verwenden.

Destructor

X::~X()
{
                        // First runs the destructor code
}
    // This is psudo code.
    // But the equiv of this code happens in every destructor
    m_c.~Z();           // Calls the destructor for each member
    // m_b              // PODs and pointers destructors do nothing
    // m_a          
    ~Y();               // Call the base class destructor
  • Wenn jede Konstruktor (einschließlich Kopie) wird erklärt, dann wird der Standard-Konstruktor wird vom Compiler nicht implementiert.
  • Wenn der Copykonstruktor deklariert wird, dann wird der Compiler nicht ein generieren.
  • Wenn der Zuweisungsoperator erklärt wird, dann wird der Compiler nicht ein generieren.
  • Wenn ein destructor der Compiler deklariert wird, wird man nicht erzeugen.

auf den Code der Suche die folgenden Kopierkonstruktoren generiert:

Foo::Foo(Foo const& copy)
    :bar(copy.bar)
{}

Bar::Bar(Bar const& copy)
    :i(copy.i)
    ,baz(copy.baz)
{}

Baz::Baz(Baz const& copy)
    :j(copy.j)
{}

Andere Tipps

Der Compiler einen Kopierkonstruktor bietet, wenn Sie erklären (Anmerkung: nicht definieren ) selbst eine Beurteilung. Der Compiler generierte Kopierkonstruktor ruft einfach die Copykonstruktor jedes Mitglied der Klasse (und jeder Basisklasse).

Das gleiche gilt für den Zuweisungsoperator und der destructor, BTW. Anders ist es für den Standard-Konstruktor, aber: dass nur durch den Compiler zur Verfügung gestellt wird, wenn Sie keinen anderen Konstruktor selbst deklarieren.

Ja, die Compiler generierte Kopierkonstruktor führt ein Mitglied weise zu kopieren, in der Reihenfolge, in der die Mitglieder in der enthaltenden Klasse deklariert sind. Wenn eine der Elementtypen nicht selbst einen Kopierkonstruktor bieten, die Möchtegern-Copy-Konstruktor der Klasse enthält, kann nicht erzeugt werden. Es kann weiterhin möglich sein, ein manuell zu schreiben, wenn Sie auf einige geeignete Mittel entscheiden können, den Wert des Elements zu initialisieren, die kopier konstruiert ist, kann nicht werden. - vielleicht von einem seiner anderen Konstrukteuren mit

Die C ++ Standard Copykonstruktor eine flach Kopie. Eine flache Kopie wird keine neue Kopien von Objekten, die Ihr ursprüngliches Objekt verweisen können; die alten und neuen Objekte werden einfach verschiedene Zeiger auf den gleichen Speicherplatz enthalten.

Der Compiler wird die benötigten Konstrukteuren für Sie generieren.

Doch sobald Sie eine Kopie-Konstruktor selbst definieren, gibt der Compiler für diese Klasse etwas zu erzeugen und geben und Fehler, wenn Sie die entsprechenden Konstrukteure haben nicht definiert ist.

Mit Ihrem Beispiel:

class Baz {
    Baz(const Baz& b) {}
    int j;
};
class Bar {
    int i;
    Baz baz;
};
class Foo {
    Bar bar;
};

Der Versuch, instantiate auf Standard oder Foo copy-Konstrukt wird einen Fehler werfen, da Baz nicht kopier konstruierbar und die Compiler können den Standard und kopieren constroctor für Foo nicht erzeugen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top