web-dev-qa-db-fra.com

Qu'est-ce qu'un constructeur non trivial en C ++?

Je lisais ceci http://en.wikipedia.org/wiki/C%2B%2B0x#Modification_to_the_definition_of_plain_old_data

Il mentionne le constructeur par défaut trivial, le constructeur de copie trivial, l'opérateur d'affectation de copie, le destructeur trivial. Qu'est-ce qui est trivial et non trivial?

63
user34537

En termes simples, une fonction membre spéciale "triviale" signifie littéralement une fonction membre qui fait son travail d'une manière très simple. La "manière simple" signifie une chose différente pour différents types de fonctions de membre spécial.

Pour un constructeur et un destructeur par défaut, être "trivial" signifie littéralement "ne rien faire du tout". Pour le constructeur de copie et l'opérateur d'affectation de copie, être "trivial" signifie littéralement "être équivalent à une simple copie de mémoire brute" (comme copier avec memcpy).

Si vous définissez un constructeur vous-même, il est considéré comme non trivial, même s'il ne fait rien, donc un constructeur trivial doit être implicitement défini par le compilateur.

Pour qu'une fonction membre spéciale satisfasse aux exigences ci-dessus, la classe doit avoir une structure très simpliste, elle ne doit pas nécessiter d'initialisations cachées lorsqu'un objet est créé ou détruit, ni aucune manipulation interne supplémentaire cachée lors de sa copie.

Par exemple, si la classe a des fonctions virtuelles, elle nécessitera des initialisations cachées supplémentaires lors de la création des objets de cette classe (initialiser la table de méthode virtuelle et autres), donc le constructeur de cette classe ne sera pas considéré comme trivial.

Pour un autre exemple, si une classe a des classes de base virtuelles, chaque objet de cette classe peut contenir des pointeurs cachés qui pointent vers d'autres parties du même objet. Un tel objet autoréférentiel ne peut pas être copié par une simple routine de copie de mémoire brute (comme memcpy). Des manipulations supplémentaires seront nécessaires pour réinitialiser correctement les pointeurs cachés dans la copie. Pour cette raison, le constructeur de copie et l'opérateur d'affectation de copie pour cette classe ne seront pas considérés comme triviaux.

Pour des raisons évidentes, cette exigence est récursive: tous les sous-objets de la classe (bases et membres non statiques) doivent également avoir des constructeurs triviaux.

74
AnT

Un constructeur d'une classe A est trivial si toutes les conditions suivantes sont vraies:

  • Il est implicitement défini (compilateur synthétisé)
  • A n'a aucune fonction virtuelle et aucune classe de base virtuelle
  • Toutes les classes de base directes de A ont des constructeurs triviaux
  • Les classes de toutes les données non statiques membres de A ont des constructeurs triviaux
30
Prasoon Saurav

Il y a déjà des réponses correctes, mais voici la citation du Standard (que je cherchais lorsque je suis tombé sur ce post):

(§12.1/5) Un constructeur par défaut est trivial s'il n'est pas fourni par l'utilisateur et si:
- sa classe n'a aucune fonction virtuelle (10.3) et aucune classe de base virtuelle (10.1), et
- aucun membre de données non statique de sa classe n'a d'initialiseur d'accolade ou égal, et
- toutes les classes de base directes de sa classe ont des constructeurs par défaut triviaux, et
- pour tous les membres de données non statiques de sa classe qui sont de type classe (ou tableau de celui-ci), chacune de ces classes a un constructeur par défaut trivial.

Cela vient de C++ 11. C++ 03 manque le deuxième élément et utilise la phrase déclarée implicitement au lieu de non fournie par l'utilisateur. Il est par ailleurs identique.

Notez que cette spécification ne couvre que les constructeurs par défaut triviaux. L'attribut Word trivial peut également être utilisé dans différents contextes, par ex. copier les constructeurs.

21
jogojapan