2010-10-13 30 views
1

Lorsque j'ai une classe qui contient des pointeurs en tant que variables membres, quel type de pointeur intelligent doit-il avoir si je ne veux pas utiliser de pointeurs simples? Ils n'ont pas besoin d'être partagés (donc pas de shared_ptr nécessaire). scoped_ptr ne fonctionnera pas car j'ai souvent besoin de construire les objets en dehors de la liste d'initialisation.Quel pointeur Smart non partagé pour les variables membres de la classe

Ou est-ce une pratique courante d'utiliser scoped_ptr lors de la création quand quelque chose peut encore échouer (exceptions levées, etc.) et de les affecter ensuite à des pointeurs simples?

+0

Pouvez-vous donner un exemple plus concret? – GManNickG

+0

Composition simple: L'objet A contient l'objet B. L'objet A crée et détruit B. Aucun autre objet ne peut influencer la durée de vie de B. – tyrondis

+2

@Benjamin: Pourquoi ne pas simplement faire de 'ObjectB' un membre sans pointeur? – GManNickG

Répondre

4

Si vous souhaitez simplement stocker des pointeurs membres dans une classe de type pointeur intelligent, vous ne pouvez pas/ne pas oublier de les supprimer, puis un choix standard sera auto_ptr. Il est dans la STL et est facilement "réinitialisé" avec la fonction reset() lorsque vous devez libérer la mémoire actuelle qui lui est allouée et la remplacer par un nouvel objet.

Vous voudrez toujours implémenter votre propre constructeur de copie et les opérateurs d'affectation pour les classes qui ont des membres auto_ptr. Cela est dû au fait que l'opérateur d'affectation auto_ptrs transfère la propriété de l'objet sous-jacent afin qu'un opérateur d'affectation par défaut n'ait pas l'effet souhaité.

Voici ce que la classe pourrait ressembler à:

class X 
{ 
public: 
    X() :p(new ClassToManage) {} 
    X(const X &copy) 
     :p(new ClassToManage(*copy.p)) 
    { 
    } 

    X &operator=(const X &rhs) 
    { 
     this->p.reset(new ClassToManage(*rhs.p)); 
    } 

private: 
    std::auto_ptr<ClassToManage> p; 
}; 

Pour tous les autres cas, je suggère boost::shared_ptr. Shared_ptr effectue le comptage des références, mais vous pouvez les stocker dans des conteneurs standard, ce qui les rend très utiles.

Vous devriez finalement essayer de vous débarrasser de l'utilisation de pointeurs simples pour tout ce qui pointe vers la mémoire allouée, il est responsable de la suppression. Si vous voulez utiliser un simple pointeur pour accéder à un tableau simple, etc., alors c'est bien (mais demandez-vous pourquoi vous n'utilisez pas std :: vector), mais quand vous les utilisez pour pointer vers quelque chose qui il est responsable de la libération alors vous demandez des ennuis. Mon objectif lors de l'écriture de code est de n'avoir aucune suppression explicite.

+0

Merci RC! Une bonne approche gardera cela à l'esprit! – tyrondis

0

Normalement j'utilise un deep_copy_ptr. En ce moment je connais loki smart_ptr et axter pointeur intelligent qui font cela. Cela permet à la classe pointeur d'être automatiquement copiée comme si elle était une variable membre normale (vous n'avez pas besoin de définir un opérateur d'affectation/constructeur de copie spécial).

Je pense que vous n'avez pas besoin de l'initialiser spécifiquement dans la liste d'initialisation (mais comme un pointeur normal, ne l'utilisez pas s'il n'a pas une valeur valide, évidemment).

1

Vous pouvez utiliser std::auto_ptr, qui était disponible avant TR1 et par conséquent votre code ne dépend pas d'un compilateur prenant en charge TR1-smartpointers.