web-dev-qa-db-ger.com

Bedingungen für die automatische Generierung von Standard- / Kopier- / Verschiebungs- und Kopier- / Verschiebungszuweisungsoperatoren?

Ich möchte meinen Speicher unter den Bedingungen auffrischen, unter denen ein Compiler normalerweise automatisch einen Standardkonstruktor, einen Kopierkonstruktor und einen Zuweisungsoperator generiert.

Ich erinnere mich, dass es einige Regeln gab, erinnere mich aber nicht und kann auch online keine seriöse Ressource finden. Kann jemand helfen?

116
oompahloompah

"Automatisch generiert" bedeutet im Folgenden "implizit als Standard deklariert, aber nicht als gelöscht definiert". Es gibt Situationen, in denen die speziellen Elementfunktionen deklariert, aber als gelöscht definiert sind.

  • Der Standardkonstruktor wird automatisch generiert, wenn kein vom Benutzer deklarierter Konstruktor vorhanden ist (§12.1/5).
  • Der Kopierkonstruktor wird automatisch generiert, wenn kein vom Benutzer deklarierter Verschiebungskonstruktor oder Verschiebungszuweisungsoperator vorhanden ist (da in C++ 03 keine Verschiebungskonstruktoren oder Verschiebungszuweisungsoperatoren vorhanden sind, wird dies in C++ 03 zu "immer" vereinfacht.) ( §12.8/8).
  • Der Kopierzuweisungsoperator wird automatisch generiert, wenn kein vom Benutzer deklarierter Verschiebungskonstruktor oder Verschiebungszuweisungsoperator vorhanden ist (§12.8/19).
  • Der Destruktor wird automatisch generiert, wenn kein vom Benutzer deklarierter Destruktor vorhanden ist (§12.4/4).

Nur C++ 11 und höher:

  • Der Verschiebungskonstruktor wird automatisch generiert, wenn kein vom Benutzer deklarierter Kopierkonstruktor, Kopierzuweisungsoperator oder Destruktor vorhanden ist und der generierte Verschiebungskonstruktor gültig ist (§12.8/10).
  • Der Verschiebungszuweisungsoperator wird automatisch generiert, wenn kein vom Benutzer deklarierter Kopierkonstruktor, Kopierzuweisungsoperator oder Destruktor vorhanden ist und der generierte Verschiebungszuweisungsoperator gültig ist (z. B. wenn keine konstanten Elemente zugewiesen werden müssten) (§12.8/21).
127
Philipp

Ich fand das Diagramm unten sehr nützlich.

C++ rules for automatic constructors and assignment operators from Sticky Bits - Eine Regel des Null-Helden werden

82
Marco M.

C++ 17 N4659-Standardentwurf

In den Abschnitten "Implizit deklariert" der folgenden cppreference-Einträge finden Sie eine kurze Querverweisliste:

Die gleichen Informationen können natürlich der Norm entnommen werden. Z.B. am C++ 17 N4659 Standardentwurf :

15.8.1 "Konstruktoren kopieren/verschieben" sagt für den Konstruktor kopieren:

6 Wenn die Klassendefinition einen Kopierkonstruktor nicht explizit deklariert, wird ein nicht expliziter Konstruktor implizit deklariert. Wenn die Klassendefinition einen Verschiebungskonstruktor oder einen Verschiebungszuweisungsoperator deklariert, wird der implizit deklarierte Kopierkonstruktor als gelöscht definiert. Andernfalls wird es als Standard definiert (11.4). Der letztere Fall ist veraltet, wenn die Klasse einen vom Benutzer deklarierten Kopierzuweisungsoperator oder einen vom Benutzer deklarierten Destruktor hat.

und für move Konstruktor:

8 Wenn die Definition einer Klasse X einen Verschiebungskonstruktor nicht explizit deklariert, wird ein nicht expliziter Konstruktor nur dann implizit als Standard deklariert, wenn

  • (8.1) - X hat keinen vom Benutzer deklarierten Kopierkonstruktor,

  • (8.2) - X hat keinen vom Benutzer deklarierten Kopierzuweisungsoperator.

  • (8.3) - X hat keinen vom Benutzer deklarierten Operator für die Zuweisung von Verschiebungen und

  • (8.4) - X hat keinen vom Benutzer deklarierten Destruktor.

15.8.2 "Kopier-/Verschiebungszuweisungsoperator" sagt für die Kopierzuweisung:

2 Wenn die Klassendefinition keinen expliziten Kopierzuweisungsoperator deklariert, wird einer implizit deklariert. Wenn die Klassendefinition einen Verschiebungskonstruktor oder einen Verschiebungszuweisungsoperator deklariert, wird der implizit deklarierte Kopierzuweisungsoperator als gelöscht definiert. Andernfalls wird es als Standard definiert (11.4). Letzterer Fall ist veraltet, wenn die Klasse über einen vom Benutzer deklarierten Kopierkonstruktor oder einen vom Benutzer deklarierten Destruktor verfügt.

und für die Zugzuteilung:

4 Wenn die Definition einer Klasse X keinen expliziten Verschiebungszuweisungsoperator deklariert, wird implizit nur dann einer als Standard deklariert, wenn

  • (4.1) - X hat keinen vom Benutzer deklarierten Kopierkonstruktor,
  • (4.2) - X hat keinen vom Benutzer deklarierten Verschiebungskonstruktor,
  • (4.3) - X hat keinen vom Benutzer deklarierten Kopierzuweisungsoperator und
  • (4.4) - X hat keinen vom Benutzer deklarierten Destruktor.

15.4 "Destruktoren" sagt es für Destruktoren:

4 Wenn eine Klasse keinen vom Benutzer deklarierten Destruktor hat, wird ein Destruktor implizit als Standard deklariert (11.4). Ein implizit deklarierter Destruktor ist ein inline public Member seiner Klasse.