Wenn Sie nicht über diese vier Methoden (sechs in C++ 11) der Compiler definieren sie für Sie generieren:
- Standardkonstruktor
- Copykonstruktor
- Zuweisungsoperator
- Destructor
- Verschieben Konstruktor (C++ 11)
- Verschieben Zuordnung (C++ 11)
Wenn Sie wissen wollen, warum?
Es ist Abwärtskompatibilität mit C (weil C-Strukturen sind kopierbar mit = und in der Deklaration). Aber es erleichtert auch das Schreiben einfacher Klassen. Einige würden argumentieren, dass es Probleme wegen des "seichten Kopierproblems" hinzufügt. Mein Argument dagegen ist, dass Sie keine Klasse mit eigenen RAW-Zeigern haben sollten. Durch Verwendung der entsprechenden Smart Pointer geht dieses Problem weg.
Standard-Konstruktor (Wenn keine anderen Konstrukteuren definiert)
Der Compiler erzeugt Standardkonstruktors die Basisklassen Standardkonstruktors rufen und dann Standardkonstruktors jedes Mitglieder (in der Reihenfolge, wie sie deklariert sind)
destructor (Wenn kein destructor definiert)
Ruft die destructor jedes Mitglieds in umgekehrter Reihenfolge der Deklaration. Ruft dann den Destruktor der Basisklasse auf.
Copy-Konstruktor (Wenn kein Kopierkonstruktor definiert ist)
Ruft die Copykonstruktor Basisklasse Leiten des src-Objekt. Ruft dann den Kopierkonstruktor jedes Elements auf, indem er die src-Objektelemente als den zu kopierenden Wert verwendet.
Zuweisungsoperator
Ruft die Zuweisungsoperator Basisklasse Leiten des src-Objekt. Dann ruft der Zuweisungsoperator jedes Mitglied auf, wobei das src-Objekt als zu kopierender Wert verwendet wird.
verschieben Konstruktor (Wenn keine Bewegung Konstruktor definiert ist)
Ruft die Bewegung Konstruktor Basisklasse Leiten des src-Objekt. Ruft dann den Verschiebungskonstruktor jedes Elements auf, wobei die src-Objektelemente als zu verschiebender Wert verwendet werden.
Verschieben Zuweisungsoperator
Ruft die Basisklasse bewegen Zuweisungsoperator das Objekt src vorbei. Dann ruft der Verschiebezuweisungsoperator für jedes Mitglied das src-Objekt als den zu kopierenden Wert auf.
Wenn Sie definieren eine Klasse wie folgt:
struct some_struct: public some_base
{
std::string str1;
int a;
float b;
char* c;
std::string str2;
};
Was der Compiler bauen ist:
struct some_struct: public some_base
{
std::string str1;
int a;
float b;
char* c;
std::string str2;
// Conceptually two different versions of the default constructor are built
// One is for value-initialization the other for zero-initialization
// The one used depends on how the object is declared.
// some_struct* a = new some_struct; // value-initialized
// some_struct* b = new some_struct(); // zero-initialized
// some_struct c; // value-initialized
// some_struct d = some_struct(); // zero-initialized
// Note: Just because there are conceptually two constructors does not mean
// there are actually two built.
// value-initialize version
some_struct()
: some_base() // value-initialize base (if compiler generated)
, str1() // has a normal constructor so just call it
// PODS not initialized
, str2()
{}
// zero-initialize version
some_struct()
: some_base() // zero-initialize base (if compiler generated)
, str1() // has a normal constructor so just call it.
, a(0)
, b(0)
, c(0) // 0 is NULL
, str2()
// Initialize all padding to zero
{}
some_struct(some_struct const& copy)
: some_base(copy)
, str1(copy.str1)
, a(copy.a)
, b(copy.b)
, c(copy.c)
, str2(copy.str2)
{}
some_struct& operator=(some_struct const& copy)
{
some_base::operator=(copy);
str1 = copy.str1;
a = copy.a;
b = copy.b;
c = copy.c;
str2 = copy.str2;
return *this;
}
~some_struct()
{}
// Note the below is pseudo code
// Also note member destruction happens after user code.
// In the compiler generated version the user code is empty
: ~str2()
// PODs don't have destructor
, ~str1()
, ~some_base();
// End of destructor here.
// In C++11 we also have Move constructor and move assignment.
some_struct(some_struct&& copy)
// ^^^^ Notice the double &&
: some_base(std::move(copy))
, str1(std::move(copy.str1))
, a(std::move(copy.a))
, b(std::move(copy.b))
, c(std::move(copy.c))
, str2(std::move(copy.str2))
{}
some_struct& operator=(some_struct&& copy)
// ^^^^ Notice the double &&
{
some_base::operator=(std::move(copy));
str1 = std::move(copy.str1);
a = std::move(copy.a);
b = std::move(copy.b);
c = std::move(copy.c);
str2 = std::move(copy.str2);
return *this;
}
};
Das ist schon eine wahnsinnig gute Antwort, aber ich würde gerne ein Beispiel mit den Smartpointern sehen. Ich war noch nie so erstaunlich bei auto_ptr – Hamy
@Hamy: Dies ist die Informationen, die Sie benötigen, um den Smart Pointer zu bauen. Wenn Sie intelligente Zeiger verwenden, müssen Sie sich darüber nicht wirklich Gedanken machen. Sie müssen sich nur um das Obige kümmern, wenn Sie RAW-eigene Zeiger in Ihrer Klasse haben. –
Diese Antwort verwirrt die Arten von [Initialisierung] (http://en.cppreference.com/w/cpp/language/initialization). Ohne Initialisierer wird die Struktur [* default initialized *] (http://en.cppreference.com/w/cpp/language/default_initialization): ihre POD-typisierten Mitglieder werden unbestimmte Werte annehmen. Mit einem leeren Initialisierer wird die Struktur [* value initialized *] (http://en.cppreference.com/w/cpp/language/value_initialization): ihre POD-typisierten Mitglieder werden [* null initialisiert *] (http : //en.cppreference.com/w/cpp/language/zero_initialization). –