2008-10-18 6 views

Répondre

15

D'abord être sûr que vous avez vraiment besoin de soutenir la copie. La plupart du temps ce n'est pas le cas, et donc désactiver les deux est la voie à suivre.

Parfois, vous devrez toujours fournir une duplication sur une classe à partir d'une hiérarchie polymorphe, dans ce cas: désactiver l'opérateur d'affectation, écrire un constructeur de copie (protégé?) Et fournir une fonction clone virtuelle. Sinon, dans le cas où vous écrivez une classe de valeur, vous êtes de retour au pays de la Forme canonique orthogonale de Coplien. Si vous avez un membre qui ne peut pas être copié de manière triviale, vous devez fournir un constructeur de copie, un destructeur, un opérateur d'affectation et un constructeur par défaut. Cette règle peut être raffinée, voir par exemple: The Law of The Big Two

Je vous recommande également d'avoir un regard sur C++ FAQ regarding assignment operators et au copy-and-swap idiom et à GOTW.

+0

Je pensais qu'il s'appelait la règle de 4. –

+0

AFAIK, il provient du livre de Jim Coplien, d'où le nom - BTW il s'applique uniquement aux classes de valeur. Certains l'appellent la règle de quatre. Il y a (était?) Aussi des explications sur/Rule of Big Three/en C++ FAQ lite (je ne le trouve plus). Et il peut être réduit à deux grâce à RAII. –

+2

Protège également contre l'auto-affectation dans l'opérateur d'affectation. –

-2

Je ne sais pas à propos de exception en toute sécurité ici mais je vais de cette façon. Imaginons qu'il s'agisse d'un wrapper de tableau structuré. J'espère que ça aide :)

Array(const Array& rhs) 
    { 
     mData = NULL; 
     mSize = rhs.size(); 
     *this = rhs; 
    } 

    Array& operator=(const Array& rhs) 
    { 
     if(this == &rhs) 
     { 
      return *this; 
     } 

     int len = rhs.size(); 

     delete[] mData; 

     mData = new T[len]; 

     for(int i = 0; i < len; ++i) 
     { 
      mData[i] = rhs[i]; 
     } 

     mSize = len; 

     return *this; 
    } 
+0

Ce code n'est pas exception en toute sécurité. Toujours attribuer avant de libérer! –

+0

Non ce n'est pas. Je n'ai eu aucun problème avec le code de sécurité des exceptions, donc je n'ai jamais eu l'occasion de le pratiquer. Celui ci-dessus est juste un snipper, normalement vous utilisez des conteneurs STL. Veuillez poster votre extrait, j'aimerais le voir. – Nazgob

+0

Il y a beaucoup de bribes dans les liens que j'ai fournis dans ma réponse. BTW, le test empêchant l'auto-affectation est maintenant considéré comme un anti-idiome (maintenant que les exceptions sont mieux comprises) –

4

Les versions générées par le compilateur fonctionnent dans la plupart des cas.

Vous devez réfléchir un peu plus au problème lorsque votre objet contient un pointeur RAW (un argument pour ne pas avoir de pointeurs RAW). Donc, vous avez un pointeur RAW, la deuxième question est que vous possédez le pointeur (est-il supprimé par vous)? Si oui, vous devrez appliquer la règle de 4.

Posséder plus d'un pointeur RAW devient de plus en plus difficile à faire correctement (L'augmentation de la complexité n'est pas linéaire non plus [mais c'est observationnel et je n'ai pas de statistiques réelles à retour cette déclaration jusqu'à]). Donc, si vous avez plus d'un pointeur RAW pensez à envelopper chacun dans sa propre classe (une certaine forme de pointeur intelligent).

Règle 4: Si un objet est le propriétaire d'un pointeur RAW, vous devez définir les 4 membres suivants pour vous assurer que vous gérez la gestion de la mémoire correctement:

  • Constructeur
  • Constructor Copie
  • Affectation opérateur
  • Destructeur

Comment vous définissez ceux-ci dépendra de la situat ions. Mais les choses à surveiller:

  • Construction Par défaut: Set pointeur NULL
  • Constructor Copy: Utilisez la copie et Swap Ideum pour fournir à la "garantie d'exception forte"
  • opérateur d'affectation: Vérifiez l'affectation
  • Destructeur: protège contre les exceptions se propageant hors du destructeur.
+0

"Les versions générées par le compilateur fonctionnent dans la plupart des situations." - Selon le type de programmation que vous faites. Même si tout est des pointeurs intelligents, traitant du suivi des ressources et des problèmes d'exception, une copie superficielle peut ne pas être ce que vous voulez sémantiquement. –

1

Essayez de lire ceci.

http://www.icu-project.org/docs/papers/cpp_report/the_anatomy_of_the_assignment_operator.html

est une très bonne analyse de l'opérateur d'affectation

+0

C'est généralement ce que je demanderais dans une interview. Cependant, je vois une fausse hypothèse: que la plupart des objets nécessitent d'être copiables. "Chaque objet dans un système C++ bien conçu a un constructeur par défaut, un constructeur de copie et un opérateur d'affectation." Cette phrase est pour les objets basés sur la valeur, pas pour les entités. –

Questions connexes