145 votes

Devrais-je préférer les pointeurs ou les références dans les données des membres?

C'est un exemple simplifié pour illustrer la question:

class A {};

class B
{
    B(A& a) : a(a) {}
    A& a;
};

class C
{
    C() : b(a) {} 
    A a;
    B b; 
};

Donc B est responsable de la mise à jour d'une partie de C. j'ai couru le code par le biais de la charpie et il whinged sur le membre de référence: peluches#1725. Cela parle de prendre soin de plus de copie par défaut et les affectations qui est assez juste, mais par défaut de copie et de cession est également mal avec les pointeurs, donc il y a peu d'avantages.

J'essaie toujours d'utiliser des références où je peux depuis nu pointeurs introduire uncertaintly savoir qui est responsable de la suppression de ce pointeur. Je préfère incorporer des objets par valeur, mais si j'ai besoin d'un pointeur, j'utilise auto_ptr dans les données membres de la classe qui détient le pointeur, et de passer de l'objet autour de lui comme une référence.

J'ai généralement l'utilisation d'un pointeur sur membre des données lorsque le pointeur peut être null ou pourraient changer. Existe-il d'autres raisons de préférer les pointeurs sur les références pour les données membres?

Est-il vrai de dire qu'un objet contenant une référence ne doivent pas être cédés, depuis une référence ne doit pas être modifié une fois initialisé?

163voto

Klaim Points 24511

Ma propre règle de base :

  • L'utilisation d'un membre de référence lorsque vous souhaitez que la durée de vie de votre objet dépend de la vie des autres objets : c'est une façon explicite-à-dire que vous ne laissez pas l'objet d'être en vie sans une instance valide d'une autre classe - en raison de l'absence de cession et de l'obligation d'obtenir les références de l'initialisation par le constructeur. C'est une bonne manière de la conception de votre classe sans présumer de rien à ce sujet en instance d'être membre ou non d'une autre classe. Vous seulement supposer que leur vie est directement liée à d'autres instances. Il vous permet de changer plus tard manière dont vous utilisez votre instance de classe (avec la nouvelle, comme une instance locale, en tant que membre de la classe, générée par un pool de mémoire dans un gestionnaire, etc.)
  • Utilisation du pointeur dans d'autres cas : Lorsque vous souhaitez que le membre à être modifié par la suite, utiliser un pointeur ou un pointeur const pour être sûr de ne lire que la pointe de l'instance. Si ce type est censé être copiable, vous ne pouvez pas utiliser les références de toute façon. Parfois, vous avez également besoin d'initialiser le membre après un appel de fonction ( init() par exemple), et puis vous n'avez pas d'autre choix que d'utiliser un pointeur. MAIS : utilisation affirme dans tous vos membres de la fonction de détecter rapidement les mauvais pointeur de l'état!
  • Dans le cas où vous souhaitez que la durée de vie des objets à être dépendant d'un objet externe de la durée de vie, et vous avez aussi besoin de ce type, pour être copiable, puis utilisez le pointeur de membres, mais de référence argument au constructeur de Cette façon, vous êtes en indiquant sur la construction que la durée de vie de cet objet dépend de l'argument de la durée de vie, MAIS la mise en œuvre utilisation de pointeurs pour toujours être copiable. Tant que ces membres sont modifiées seulement par la copie, et votre type de ne pas avoir un constructeur par défaut, le type doit remplir les deux objectifs.

70voto

James Hopkin Points 8318

Éviter de référence des membres, car ils restreignent ce que la mise en œuvre d'une classe peut le faire (y compris, comme vous le mentionnez, la prévention de la mise en œuvre d'un opérateur d'affectation) et ne fournissent aucun avantage à ce que la classe peut fournir.

Exemple de problèmes:

  • vous êtes obligé d'initialiser la référence de chaque constructeur initialiser la liste: il n'y a aucun moyen de factoriser ce initialisation dans une autre fonction (jusqu'à ce que le C++0x, de toute façon)
  • la référence ne peut pas être reprise ou la valeur null. Cela peut être un avantage, mais si le code a jamais besoin de changer pour permettre de reliaison ou pour le membre est nul, toutes les utilisations de la membre a besoin de changement
  • à la différence de pointeur membres, les références ne peuvent pas être facilement remplacés par des pointeurs intelligents ou les itérateurs comme refactoring peut nécessiter

38voto

Mykola Golubyev Points 21210

Objets rarement devrait permettre d'attribuer et d'autres trucs comme comparaison. Si vous envisagez de certains modèle d'affaires avec tous les objets 'Département', 'Employé', 'Directeur', il est difficile d'imaginer un cas où un employé sera affecté à d'autres.

Donc, pour les objets d'entreprise, il est très bon pour décrire un-à-un et un-à-plusieurs liens comme des références et non des pointeurs.

Et probablement que c'est OK pour décrire un ou zéro de la relation comme un pointeur.

Donc pas de 'nous ne pouvons pas nous affecter", puis facteur.
Beaucoup de programmeurs juste s'habituer avec les pointeurs et c'est pourquoi ils vont trouver n'importe quel argument pour éviter l'utilisation de la référence.

Avoir un pointeur comme un membre de la force que vous ou un membre de votre équipe pour vérifier que le pointeur de nouveau et de nouveau avant de l'utiliser, avec des "en cas" en commentaire. Si un pointeur peut être à zéro, alors le pointeur est probablement utilisé comme une sorte de drapeau, ce qui est mauvais, comme tous les objets ont à jouer son propre rôle.

12voto

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X