10

Ceci est juste une question rapide à comprendre correctement ce qui se passe lorsque vous créez une classe avec un constructeur comme celui-ci:compilateur généré constructeurs

class A 
{ 
    public: 
    A() {} 
}; 

Je sais qu'aucun constructeur par défaut est généré car il est déjà défini, mais sont constructeurs de copie et d'affectation générés par le compilateur ou en d'autres termes dois-je déclarer un constructeur de copie privée et un opérateur d'assignation privée afin d'éviter que cela se produise?

class A 
{ 
    private: 
    // needed to prevent automatic generation? 
    A(const A&); 
    A& operator=(const A&); 
    public: 
    A() {} 
}; 

Répondre

10

Oui. Le constructeur de copie, l'opérateur d'affectation et le destructeur sont toujours créés indépendamment des autres constructeurs et opérateurs.

Si vous voulez en désactiver un, ce que vous avez là est parfait. C'est assez commun aussi.

+0

En effet, bien que si vous utilisez cette fonction pour empêcher la copie/cession, consultez [boost :: noncopyable] (http: // www .boost.org/doc/libs/1_55_0/libs/utilitaire/utilitaire.htm # Class_noncopyable). (Vous pouvez déchirer cette classe simple ou écrire la vôtre et la réutiliser où vous voulez.) – TypeIA

13

Oui, les opérateurs de copie de constructeur et d'assignation de copie sont toujours créés même si vous déclarez votre propre constructeur par défaut.

La création de ceux-ci est seulement supprimée si vous déclarez votre propre constructeur de copie ou opérateur d'affectation de copie dans la définition de classe respectivement.

Notez qu'il est possible d'avoir à la fois votre propre constructeur de copie et un compilateur fourni un:

struct A { 
    A() { } 
    A(A const&, int foo); 
}; // compiler declares a copy constructor now 

// make the second parameter have a default argument 
// now this constructor is a copy constructor too. 
inline A::A(A const&, int foo = 0) { 

} 

int main() { 
    A a; 
    A b = a; // ambiguity between compiler's one and our custom one! 
} 

La norme permet cependant compilateurs d'accepter ce code - mais l'effet est similaire à avoir un comportement non défini: Le programme est mal formé, mais aucun avertissement/erreur n'est requis pour ce programme. (Les premières versions de GCC ne rejettent pas ce code, les plus récentes le rejettent).

+1

Vos messages sont "comme d'habitude" très instructif :) –

2

Si vous souhaitez désactiver la copie et l'affectation, il peut être préférable d'hériter d'une classe disposant d'un constructeur de copie privée et d'un opérateur d'affectation (boost::noncopyable est un ready-made).

1) Dactylographie moins répétitive.

2) Auto-documenté (j'espère). 3) Plus fort vérifie que ces opérations ne peuvent pas être invoquées (la classe elle-même, ni les amis ne peuvent faire de copies non plus - ce qui aboutirait à un compilateur, pas à une erreur de linker).

4) ne cacherons pas le constructeur par défaut :)

#include <boost/noncopyable.hpp> 

class X : boost::noncopyable 
{ 
}; 

int main() 
{ 
    X a, b;  //has default constructor 
    //X c(a); //but can't be copied 
    //a = b; //or assigned 
}