
FAQ C++Consultez toutes les FAQ
Nombre d'auteurs : 34, nombre de questions : 368, derni�re mise � jour : 14 novembre 2021 Ajouter une question
Cette FAQ a �t� r�alis�e � partir des questions fr�quemment pos�es sur les forums de http://www.developpez.com et de l'exp�rience personnelle des auteurs.
Je tiens � souligner que cette FAQ ne garantit en aucun cas que les informations qu'elle propose sont correctes ; les auteurs font le maximum, mais l'erreur est humaine. Cette FAQ ne pr�tend pas non plus �tre compl�te. Si vous trouvez une erreur ou si vous souhaitez devenir r�dacteur, lisez ceci.
Sur ce, nous vous souhaitons une bonne lecture.
- Qu'est-ce qu'une classe copiable ?
- Je n'ai pas de constructeur par copie ni d'op�rateur d'affectation (operator=) : ma classe est-elle copiable ?
- Toute classe doit-elle �tre copiable ?
- Comment rendre une classe non copiable ?
- Que se passe-t-il pour les classes d�riv�es d'une classe non copiable ?
- Quelle solution pr�f�rer (h�ritage ou red�finition) pour rendre une classe non copiable ?
- Comment rendre une classe non copiable en C++0x ?
Une classe copiable permet � ses instances d'�tre copi�es � l'identique d'un contenant vers un autre. En C++, syntaxiquement cette propri�t� est v�rifi�e d�s qu'une classe poss�de un constructeur par copie ou un op�rateur d'affectation.
Code c++ : | S�lectionner tout |
1 2 | copyable a; copyable b = a; // ou copyable b(a); |
Code c++ : | S�lectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | class copy_with_problems { public: copy_with_problems() : m_probleme(new Type()) {} copy_with_problems(copy_with_problems const & copie_) : m_probleme(copie_.m_probleme) {} copy_with_problems& operator=(copy_with_problems const & rhs_) { delete m_probleme; m_probleme = copie_.m_probleme; return *this; } ~copy_with_problems() { delete m_probleme; } private: Type *m_probleme; }; int main() { copy_with_problems my_object; { copy_with_problems a_copy(my_object); } // au sortir on d�truit le pointeur de a_copy qui est le m�me que celui // de my_object // ici my_object.m_probleme pointe sur une zone invalide ! } |







Le compilateur g�n�re des versions par d�faut du constructeur par copie et de l'op�rateur=.
Le constructeur par copie g�n�r� par le compilateur correspond � un appel du constructeur par copie des classes parentes et du constructeur par copie des membres.
Le comportement est le m�me pour l'op�rateur = par d�faut.
Notons toutefois que l'op�rateur d'affectation ne peut �tre g�n�r� par le compilateur si la classe poss�de un membre constant ou un membre r�f�rence. Le constructeur par copie implicite est bien g�n�r� mais pas l'op�rateur =.
De fa�on analogue, si la classe poss�de un membre non copiable alors ni le constructeur par copie ni l'op�rateur d'affectation implicites ne peuvent �tre g�n�r�s par le compilateur.
Peut-on autant dire que notre classe est copiable ? Non. Certes syntaxiquement un objet de cette classe peut �tre copi�. Mais il faut encore v�rifier si s�mantiquement cela a une coh�rence et ne risque pas de poser de probl�me. Une syntaxe correcte vous garantit que votre code compile, une s�mantique bien d�finie assure une ex�cution ma�tris�e.
Non. Par exemple, une classe � s�mantique d'entit� ne doit pas �tre recopi�e. De m�me certaines enveloppes RAII (
Resource Acquisition Is Initialization ) peuvent avoir une politique interdisant la copie (par exemple un ScopedMutex). Citons encore les singletons.
Pour rendre une classe non copiable, il faut d�clarer son constructeur par copie et son op�rateur d'affectation en priv� sans les d�finir :
Code c++ : | S�lectionner tout |
1 2 3 4 5 6 7 8 9 | class non_copyable { public: non_copyable(){} //... private: non_copyable(non_copyable const &);// pas de d�finition ! non_copyable& operator=(non_copyable const &);// pas de d�finition ! }; |
Ne pas les d�finir emp�che de les appeler � l'int�rieur de la classe. L'erreur appara�t alors � l'�dition de lien.
Si la classe d�riv�e ne red�finit pas son constructeur par copie et/ou son op�rateur d'affectation, la propri�t� non copiable est conserv�e :
Code c++ : | S�lectionner tout |
1 2 3 4 5 | class derived : private non_copyable { public: derived(){} }; |
Code c++ : | S�lectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 | class derived : private non_copyable { public: derived(){} derived(derived const &){} derived& operator=(derived const &) { return *this; } }; derived a; derived b(a); // OK derived c; c = a;// OK |
Boost propose une classe boost::noncopyable avec un constructeur par copie et un op�rateur d'affectation priv�s non d�finis :
Code c++ : | S�lectionner tout |
1 2 3 4 5 6 7 | #include <boost/noncopyable.hpp> class my_class_non_copyable : private boost::noncopyable { public: my_class_non_copyable(){} }; |

Nous avons donc deux solutions pour rendre une classe non copiable : d�clarer son constructeur par copie et son op�rateur d'affectation sans les d�finir ou h�riter d'une classe non copiable (par exemple, boost::noncopyable). La seconde approche est pr�f�rable, en particulier car les compilateurs peuvent avoir des comportements diff�rents sur des aspects particuliers. Par exemple, le SFINAE ( Substitution Failure Is Not An Error) dans le code suivant ne se comporte pas de fa�on identique sur visual et gcc :
Code c++ : | S�lectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | #include <iostream> template <typename T1, typename T2> struct CanConvert { typedef char True; class False { char dummy[2]; }; static True canConvert( T2 ); static False canConvert( ... ); static T1 makeT1( ); enum { r = sizeof(canConvert( makeT1( ) )) == sizeof(True) }; }; struct non_copyable { non_copyable() {} private: non_copyable(non_copyable const&); non_copyable& operator=(non_copyable const&); }; struct S1 { S1(int) {} private: S1(S1 const& ); S1& operator=(S1 const&); }; struct S2 : private non_copyable { S2(int) {} private: }; int main (int argc, char **argv) { std::cout << CanConvert<char, S1>::r << std::endl; std::cout << CanConvert<int*, S1>::r << std::endl; std::cout << CanConvert<char, S2>::r << std::endl; std::cout << CanConvert<int*, S2>::r << std::endl; } |
Le C++0x introduit un nouveau m�canisme facilitant l'�criture de classe non copiable : la suppression de fonction gr�ce � la syntaxe � =delete �.
Cette syntaxe permet de d�clarer une fonction tout en supprimant sa d�finition. Elle peut s'appliquer aux fonctions membres sp�ciales (constructeurs, constructeur par copie, destructeur, op�rateurs), ainsi qu'aux fonctions membres et aux fonctions libres - bref, � toutes les fonctions.
Pour rendre une classe non copiable, il faut supprimer son constructeur par copie et son op�rateur d'affectation :
Code c++ : | S�lectionner tout |
1 2 3 4 5 6 7 8 9 10 | class non_copyable { public: // force le compilateur � g�n�rer la version par d�faut du constructeur. non_copyable() = default; // suppression du constructeur par copie et de l'op�rateur d'affectation non_copyable(const non_copyable &) = delete; non_copyable & operator= (const non_copyable &) = delete; }; |
- La syntaxe pour supprimer une fonction est claire et non-ambig�e.
- L'appel � une fonction supprim�e �choue � la compilation, jamais � l'�dition des liens.
- Le message d'erreur est plus explicite et pointe directement sur la fonction supprim�e.
Notez �galement l'utilisation de la syntaxe � =defaut � pour r�cup�rer un constructeur par d�faut g�n�r� automatiquement par le compilateur.
Proposer une nouvelle r�ponse sur la FAQ
Ce n'est pas l'endroit pour poser des questions, allez plut�t sur le forum de la rubrique pour �aLes sources pr�sent�es sur cette page sont libres de droits et vous pouvez les utiliser � votre convenance. Par contre, la page de pr�sentation constitue une �uvre intellectuelle prot�g�e par les droits d'auteur. Copyright � 2025 Developpez Developpez LLC. Tous droits r�serv�s Developpez LLC. Aucune reproduction, m�me partielle, ne peut �tre faite de ce site et de l'ensemble de son contenu : textes, documents et images sans l'autorisation expresse de Developpez LLC. Sinon vous encourez selon la loi jusqu'� trois ans de prison et jusqu'� 300 000 � de dommages et int�r�ts.