web-dev-qa-db-fra.com

Conditions pour la génération automatique du ctor par défaut / copier / déplacer et de l'opérateur d'affectation de copie / déplacement?

Je souhaite rafraîchir ma mémoire sur les conditions dans lesquelles un compilateur génère généralement automatiquement un constructeur par défaut, un constructeur de copie et un opérateur d'affectation.

Je me souviens qu'il y avait des règles, mais je ne me souviens pas et je ne trouve pas non plus de ressource fiable en ligne. Quelqu'un peut-il aider?

116
oompahloompah

Dans ce qui suit, "généré automatiquement" signifie "implicitement déclaré comme étant par défaut, mais non défini comme supprimé". Dans certaines situations, les fonctions membres spéciales sont déclarées, mais définies comme supprimées.

  • Le constructeur par défaut est généré automatiquement s'il n'y a pas de constructeur déclaré par l'utilisateur (§12.1/5).
  • Le constructeur de copie est généré automatiquement s'il n'y a pas de constructeur de déplacement ou d'opérateur d'affectation de déplacement déclaré par l'utilisateur (car il n'y a pas de constructeur de déplacement ni d'opérateur d'affectation de déplacement en C++ 03, cela se simplifie en "toujours" en C++ 03) ( §12.8/8).
  • L'opérateur d'affectation de copie est généré automatiquement s'il n'y a pas de constructeur de déplacement ou d'opérateur d'affectation de déplacement déclaré par l'utilisateur (§12.8/19).
  • Le destructeur est généré automatiquement s'il n'y a pas de destructeur déclaré par l'utilisateur (§12.4/4).

C++ 11 et versions ultérieures uniquement:

  • Le constructeur de déplacement est généré automatiquement s'il n'y a pas de constructeur de copie, d'opérateur d'affectation de copie ou de destructeur déclaré par l'utilisateur et si le constructeur de déplacement généré est valide (§12.8/10).
  • L'opérateur d'affectation de déplacement est généré automatiquement s'il n'y a pas de constructeur de copie, d'opérateur d'affectation de copie ou de destructeur déclaré par l'utilisateur, et si l'opérateur d'affectation de déplacement généré est valide (par exemple s'il n'a pas besoin d'affecter des membres constants) (§12.8/21).
127
Philipp

J'ai trouvé le diagramme ci-dessous très utile.

C++ rules for automatic constructors and assignment operators de Sticky Bits - Devenir une règle de Zero Hero

82
Marco M.

Projet standard C++ 17 N4659

Pour une référence croisée standard rapide, consultez les sections "Implicitement-déclarées" des entrées cppreference suivantes:

Les mêmes informations peuvent bien sûr être obtenues à partir de la norme. Par exemple. le projet standard C++ 17 N4659 :

15.8.1 "Copier/déplacer les constructeurs" dit pour le constructeur de copie:

6 Si la définition de classe ne déclare pas explicitement un constructeur de copie, un constructeur non explicite est déclaré implicitement. Si la définition de classe déclare un constructeur de déplacement ou un opérateur d'affectation de déplacement, le constructeur de copie déclaré implicitement est défini comme supprimé; sinon, il est défini comme défaut (11.4). Ce dernier cas est obsolète si la classe a un opérateur d'affectation de copie déclaré par l'utilisateur ou un destructeur déclaré par l'utilisateur.

et pour déplacer constructeur:

8 Si la définition d'une classe X ne déclare pas explicitement un constructeur de déplacement, un constructeur non explicite sera implicitement déclaré comme défaut si et seulement si

  • (8.1) - X n'a ​​pas de constructeur de copie déclaré par l'utilisateur,

  • (8.2) - X n'a ​​pas d'opérateur d'affectation de copie déclaré par l'utilisateur,

  • (8.3) - X n'a ​​pas d'opérateur d'affectation de déplacement déclaré par l'utilisateur, et

  • (8.4) - X n'a ​​pas de destructeur déclaré par l'utilisateur.

15.8.2 "Opérateur d'affectation de copie/déplacement" indique pour l'affectation de copie:

2 Si la définition de classe ne déclare pas explicitement un opérateur d'affectation de copie, un est déclaré implicitement. Si la définition de classe déclare un constructeur de déplacement ou un opérateur d'affectation de déplacement, l'opérateur d'affectation de copie déclaré implicitement est défini comme supprimé; sinon, il est défini comme défaut (11.4). Ce dernier cas est obsolète si la classe a un constructeur de copie déclaré par l'utilisateur ou un destructeur déclaré par l'utilisateur.

et pour l'affectation de déménagement:

4 Si la définition d'une classe X ne déclare pas explicitement un opérateur d'affectation de déplacement, un sera implicitement déclaré comme défaut si et seulement si

  • (4.1) - X n'a ​​pas de constructeur de copie déclaré par l'utilisateur,
  • (4.2) - X n'a ​​pas de constructeur de déplacement déclaré par l'utilisateur,
  • (4.3) - X n'a ​​pas d'opérateur d'affectation de copie déclaré par l'utilisateur, et
  • (4.4) - X n'a ​​pas de destructeur déclaré par l'utilisateur.

15.4 "Destructeurs" le dit pour les destructeurs:

4 Si une classe n'a pas de destructeur déclaré par l'utilisateur, un destructeur est implicitement déclaré comme par défaut (11.4). Un destructeur déclaré implicitement est un membre public en ligne de sa classe.