IdentifiantMot de passe
Loading...
Mot de passe oubli� ?Je m'inscris ! (gratuit)
logo

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.

SommaireLes classes en C++S�mantique de copie (7)
pr�c�dent sommaire suivant
 

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);
S�mantiquement, il faut n�anmoins prendre garde � ce que la copie d'un objet n'entra�ne pas des effets ind�sirables :

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 ! 
}

Mis � jour le 15 octobre 2009 3DArchi

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.

Mis � jour le 15 octobre 2009 3DArchi

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.

Mis � jour le 15 octobre 2009 3DArchi

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 ! 
};
Les rendre private emp�che de pouvoir les appeler � l'ext�rieur de la classe. Le compilateur g�n�re une erreur si on tente de les appeler.
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.

Mis � jour le 15 octobre 2009 3DArchi

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(){} 
};
Cependant, la propri�t� peut se perdre si vous red�finissez le constructeur par copie ou l'op�rateur d'affectation sans faire appel � la m�thode parente :

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
Le constructeur non_copyable appel� dans derived(derived const &) est ici le constructeur par d�faut non_copyable().

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(){} 
};
L'h�ritage boost::noncopyable doit �tre priv�. Une premi�re raison est que boost::noncopyable ne poss�de pas de destructeur virtuel public ! Ensuite, l'utilisation polymorphe de boost::noncopyable n'a pas de sens. Enfin, boost::noncopyable ne proposant pas de membres utilitaires qui peuvent �tre appel�s par les classes d�riv�es, un h�ritage protected ne se justifie pas.

Mis � jour le 15 octobre 2009 3DArchi

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; 
  
}

Mis � jour le 15 octobre 2009 3DArchi Luc Hermitte

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; 
};
Cette approche poss�de quelques avantages par rapport � l'astuce utilis�e en C++03 :
  • 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.

Mis � jour le 15 octobre 2009 Arzar

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 �a


R�ponse � la question

Liens sous la question
pr�c�dent sommaire suivant
 

Les 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.