8 Stimmen

C++11 Compiler generierte Funktionen

Sagen Sie eine Klasse

Klasse Stück {} ;

Wenn ich richtig liege, sollte das äquivalent sein zu :

Klasse Stück {
   //C++ 03
    Stück ();                          //Standardkonstruktor
    Stück( const Stück&);              //Kopierkonstruktor
    Stück& operator=(const Stück&);    //Kopierzuweisungsoperator
    ~Stück();                          //Destruktor

    //Seit C++ 11
    Stück(Stück&&);                   //Bewegungskonstruktor
    Stück& operator=(Stück&&);        //Bewegungszuweisungsoperator
};

Also, was kann ich über diese sagen ?

a)

Klasse Bauer{
    ~Bauer() {}// Nur Destruktor
};

b)

Klasse Läufer{
    Läufer(Läufer&& ) {}// Nur Bewegungskonstruktor
};

c)

Klasse Springer{
    Springer(Springer&&, int =0) {} // Bewegungskonstruktor, wenn kein zweites Argument vorhanden ist
};

d)

Klasse Turm {
    Turm(const Turm& ) {}// Nur Kopierkonstruktor
};

e)

Klasse König{
        König& operator=(const König&) = löschen;
    };

Meiner Ansicht nach wird der Compiler generieren für :

  • a) Standardkonstruktor, Kopierkonstruktor, Kopierzuteilungsoperator, ( Bewegungskonstruktor/Bewegungszuteilungsoperator ? )
  • b) Destruktor
  • c) Destruktor
  • d) Kopierzuteilungsoperator und Destruktor ( Bewegungskonstruktor/Bewegungszuteilungsoperator ? )
  • e) Standardkonstruktor, Kopierkonstruktor, Destruktor, ( Bewegungskonstruktor/Bewegungszuteilungsoperator ? )

Habe ich recht oder fehlt mir etwas hier ?

Grundsätzlich gibt es irgendwelche neuen Regeln in C++11 für die Generierung von Funktionen, wenn sie nicht vom Benutzer bereitgestellt werden ?

7voto

dyp Punkte 37134

Ich werde hier einige irrelevante Punkte auslassen, z.B. über unions, Basisklassen, geschweifte oder gleich initialisierte usw. Wenn Ihre Klassen Mitglieder, Basisklassen, ... haben, dann wird die Antwort anders aussehen. Zum Beispiel, wenn Sie ein const Mitglied haben, würde ein implizit deklarierter Zuweisungsoperator als gelöscht definiert werden.

Standardkonstruktor

[class.ctor]/5

Ein Standardkonstruktor für eine Klasse X ist ein Konstruktor der Klasse X, der ohne Argument aufgerufen werden kann. Wenn kein benutzerdeklarierter Konstruktor für die Klasse X existiert, wird ein Konstruktor ohne Parameter implizit als standardmäßig deklariert. Ein implizit deklarierter Standardkonstruktor ist ein inline öffentliches Element seiner Klasse. Ein standardmäßig deklarierter Standardkonstruktor für die Klasse X wird als gelöscht definiert, wenn [... hier viele irrelevante Punkte folgen].

Also in den Fällen a) und e) [ohne benutzerdeklarierten Konstruktor], wird ein Standardkonstruktor als standardmäßig deklariert.

Standarddestruktor

[class.dtor]

4 Wenn eine Klasse keinen benutzerdeklarierten Destruktor hat, wird ein Destruktor implizit als standardmäßig deklariert. Ein implizit deklarierter Destruktor ist ein inline öffentliches Element seiner Klasse.

5 Ein standardmäßig deklarierter Destruktor für eine Klasse X wird als gelöscht definiert, wenn [... hier viele irrelevante Punkte folgen]

Also in allen Fällen außer a) [mit einem benutzerdeklarierten dtor] wird ein Standarddestruktor implizit deklariert und implizit definiert, wenn er odr-verwendet wird.


Wie in [class.copy]/2+3 dargelegt, können ein Kopierkonstruktor und ein Bewegungskonstruktor zusätzliche Parameter haben, wenn diese Standardwerte haben.

Kopierkonstruktor

Ein Kopierkonstruktor wird implizit deklariert, wenn kein benutzerdefinierter Kopierkonstruktor existiert (ein Konstruktorvorlage ist niemals ein Kopierkonstruktor). [class.copy]/7

Wenn die Klassendefinition einen Bewegungskonstruktor oder eine Bewegungszuweisungsoperator deklariert, wird der implizit deklarierte Kopierkonstruktor als gelöscht definiert; sonst wird er als standardmäßig definiert. Im letzteren Fall ist es veraltet, wenn die Klasse einen benutzerdeklarierten Kopierzusweisungsoperator oder einen benutzerdeklarierten Destruktor hat.

Das bedeutet, in allen Fällen außer d) [mit einem benutzerdeklarierten Kopierkonstruktor] wird ein Kopierkonstruktor implizit deklariert. In den Fällen b) und c) [mit einem benutzerdefinierten Bewegungskonstruktor] wird der Kopierkonstruktor als gelöscht definiert. Für a) [benutzerdeklarierter Destruktor] und e) [benutzerdeklarierter Kopierzuteilungsoperator] kann er als standardmäßig definiert sein, aber das ist veraltet.

Bewegungskonstruktor

Der Bewegungskonstruktor wird in diesen Fällen nicht einmal deklariert [class.copy]/9

  • X hat keinen benutzerdeklarierten Kopierkonstruktor,
  • X hat keinen benutzerdeklarierten Kopierzuteilungsoperator,
  • X hat keinen benutzerdeklarierten Bewegungszuweisungsoperator,
  • X hat keinen benutzerdeklarierten Destruktor, und
  • der Bewegungskonstruktor würde nicht implizit als gelöscht definiert werden.

Es gibt wieder einige Fälle, in denen er als gelöscht definiert werden würde, aber diese treffen hier nicht zu.

Der Bewegungskonstruktor wird also nicht in einem der Fälle deklariert.


Kopierzuteilungsoperator

In [class.copy]/18:

Wenn die Klassendefinition nicht explizit einen Kopierzuteilungsoperator deklariert, wird er implizit deklariert. Wenn die Klassendefinition einen Bewegungskonstruktor oder einen Bewegungszuweisungsoperator deklariert, wird der implizit deklarierte Kopierzuteilungsoperator als gelöscht definiert; sonst wird er als standardmäßig definiert. Im letzteren Fall ist es veraltet, wenn die Klasse einen benutzerdeklarierten Kopierkonstruktor oder einen benutzerdeklarierten Destruktor hat.

Er wird in einigen Fällen als gelöscht definiert, siehe [class.copy]/23, aber diese treffen hier nicht zu.

Der Kopierzuteilungsoperator wird in allen Fällen außer e) [benutzerdeklarierter Kopierzuteilungsoperator] deklariert. Er wird in b) und c) [beide: benutzerdefinierter Bewegungskonstruktor] als gelöscht definiert; und er kann in a) [benutzerdeklarierter Destruktor] und d) [benutzerdeklarierter Kopierkonstruktor] als standardmäßig definiert sein. Beachten Sie die Parallele zum Kopierkonstruktor.

Bewegungszuweisungsoperator

Ähnlich wie beim Bewegungskonstruktor wird der Bewegungszuweisungsoperator nicht einmal deklariert, wenn entweder [class.copy]/20:

  • X hat keinen benutzerdeklarierten Kopierkonstruktor,
  • X hat keinen benutzerdeklarierten Bewegungskonstruktor,
  • X hat keinen benutzerdeklarierten Kopierzuteilungsoperator,
  • X hat keinen benutzerdeklarierten Destruktor, und
  • der Bewegungszuweisungsoperator würde nicht implizit als gelöscht definiert werden.

Er wird in einigen Fällen als gelöscht definiert, siehe [class.copy]/23 (derselbe Absatz wie beim Kopierkonstruktor), aber diese treffen hier nicht zu.

Ein Bewegungszuweisungsoperator wird implizit deklariert und als standardmäßig definiert in keinem der Fälle.

3voto

P0W Punkte 46279

Beim Betrachten einiger Beiträge und Online-Tutorials kam ich zu folgendem Schluss:

Generierte Funktionen :-

  • C++ 03:

    1) Standardkonstruktor (nur generiert, wenn vom Benutzer kein Konstruktor deklariert wird)

    2) Kopierkonstruktor (nur generiert, wenn Nr. 5,6 vom Benutzer deklariert werden)

    3) Kopierzuweisungsoperator (nur generiert, wenn 5,6 nicht vom Benutzer deklariert werden)

    4) Destruktor

  • Seit C++ 11:

    5) Move-Konstruktor (nur generiert, wenn 2,3,4,6 nicht vom Benutzer deklariert werden)

    6) Move-Zuweisungsoperator (nur generiert, wenn 2,3,4,5 nicht vom Benutzer deklariert werden)


Also für

a)

class Bauer{ //1, 2, 3
    ~Bauer() {}// Nur Destruktor
};

b)

class Läufer{ //4
    Läufer(Läufer&& ) {}
};

c)

class Springer{ //4
    Springer(Springer&&, int =0) {} 
};

d)

class Turm{ //3, 4
    Turm(const Turm& ) {}
};

e)

class König{ //1, 2, 4
        König& operator=(const König&) = delete;
    };

Bearbeiten : Wie von DyP kommentiert:-

In C++11,

Für Fall a), sind 2 und 3 veraltet.

Für Fall d), ist 3 veraltet.

Für Fall e), ist 2 veraltet.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X