2177 votes

Qu'est ce qu'un pointeur intelligent et quand dois-je utiliser?

Qu'est ce qu'un pointeur intelligent et quand dois-je utiliser?

2053voto

Lloyd Points 7111

Un pointeur intelligent est une classe qui encapsule un "nu" pointeur C++, pour gérer la durée de vie de l'objet pointé.

Avec "nue" C++ les pointeurs, le programmeur doit explicitement la destruction de l'objet lorsqu'il n'est plus utile.

// Need to create the object to achieve some goal
MyObject* ptr = new MyObject(); 
ptr->DoSomething();// Use the object in some way.
delete ptr; // Destroy the object. Done with it.
// Wait, what if DoSomething() raises an exception....

Un pointeur intelligent par rapport définit une politique que lorsque l'objet est détruit. Vous avez encore à créer l'objet, mais vous n'avez plus à vous soucier de le détruire.

SomeSmartPtr<MyObject> ptr(new MyObject());
ptr->DoSomething(); // Use the object in some way.

// Destruction of the object happens, depending 
// on the policy the smart pointer class uses.

// Destruction would happen even if DoSomething() 
// raises an exception

Le plus simple politique implique la portée de pointeur intelligent objet wrapper, tels que mis en œuvre par boost::scoped_ptr ou std::unique_ptr.

void f()
{
    {
       boost::scoped_ptr<MyObject> ptr(new MyObject());
       ptr->DoSomethingUseful();
    } // boost::scopted_ptr goes out of scope -- 
      // the MyObject is automatically destroyed.

    // ptr->Oops(); // Compile error: "ptr" not defined
                    // since it is no longer in scope.
}

Notez que scoped_ptr instances ne peuvent pas être copiés. Cela empêche le pointeur d'être supprimé à plusieurs reprises (à tort). Cependant, vous pouvez transmettre références à d'autres fonctions que vous appelez.

L'étendue des pointeurs sont utiles lorsque vous souhaitez attacher la durée de vie de l'objet à un bloc de code particulier, ou si vous avez intégré comme membre des données à l'intérieur d'un autre objet, la durée de vie de cet autre objet. L'objet existe jusqu'à ce que le contenant bloc de code est exitted, ou jusqu'à ce que le contenant de l'objet est lui-même détruit.

De plus en plus complexe smart pointeur de la politique implique de comptage de référence le pointeur. Cela permet le pointeur à être copié. Lors de la dernière "de référence" de l'objet est détruit, l'objet est supprimé. Cette politique est mise en œuvre par boost::shared_ptr et std::shared_ptr.

void f()
{
    typedef std::tr1::shared_ptr<MyObject> MyObjectPtr; // Nice short alias.
    MyObjectPtr p1; // Empty
    {
        MyObjectPtr p2(new MyObject());
        // There is now one "reference" to the created object
        p1=p2; // Copy the pointer.
        // There are now two references to the object.
    } // p2 is destroyed, leaving one reference to the object.
} // p1 is destroyed, leaving a reference count of zero. 
  // The object is deleted.

Référence compté les pointeurs sont très utiles lorsque la durée de vie de votre objet est beaucoup plus compliqué, et n'est pas liée directement à une section particulière du code ou à un autre objet.

Il ya un inconvénient à un décompte de références pointeurs - la possibilité de créer une balançant de référence.

// Create the smart pointer on the heap
MyObjectPtr* pp = new MyObjectPtr(new MyObject())
// Hmm, we forgot to destroy the smart pointer,
// because of that, the object is never destroyed!

Une autre possibilité est de créer des références circulaires.

struct Owner {
   boost::shared_ptr<Owner> other;
};

boost::shared_ptr<Owner> p1 (new Owner());
boost::shared_ptr<Owner> p2 (new Owner());
p1->other = p2; // p1 references p2
p2->other = p1; // p2 references p1

// Oops, the reference count of of p1 and p2 never goes to zero!
// The objects are never destroyed!

Pour contourner ce problème, à la fois de stimuler et de C++11 définissent weak_ptr pour définir une faible (innombrables) la référence à une shared_ptr.

Notez également que la bibliothèque C++ standard définit un type spécial de pointeur intelligent std::auto_ptr. Il est très semblable à une étendue de pointeur, sauf qu'il a aussi le "spécial" dangereux capacité à être copié - qui de façon inattendue transfère la propriété!

std::auto_ptr<MyObject> p1 (new MyObject());
std::auto_ptr<MyObject> p2 = p1; // Copy and transfer ownership. 
                                 // p1 gets set to empty!
p2->DoSomething(); // Works.
p1->DoSomething(); // Oh oh. Hopefully raises some NULL pointer exception.

122voto

sergtk Points 3109

Smart pointeur est un pointeur de type avec des fonctionnalités supplémentaires, par exemple libération automatique de la mémoire, de comptage de référence, etc.

Petite intro est disponible sur la page des Pointeurs Intelligents - qui, Quoi, Pourquoi, Qui?.

Un simple smart-type de pointeur est - std::auto_ptr (chapitre 20.4.5 de la norme C++), ce qui permet à la désallocation de la mémoire automatiquement lorsqu'il hors de portée et ce qui est plus robuste que la simple utilisation du pointeur lorsque les exceptions sont les jeter, bien que moins souple.

Un autre type de pratique est - boost::shared_ptr qui met en œuvre de comptage de référence et automatiquement désallouer de la mémoire lors de l'absence de références à l'objet demeurent, ce qui contribue à éviter les fuites de mémoire, il est facile à utiliser pour mettre en œuvre RAII.

Le sujet est traité en profondeur dans le livre "C++ Modèles: Le Guide Complet" de David Vandevoorde, Nicolai M. Josuttis, chapitre 20. Les Pointeurs Intelligents. Quelques thèmes abordés:

47voto

Sridhar Iyer Points 1186

Définitions de Chris,Sergdev et Llyod est correct. Je préfère une définition plus simple si, juste pour garder ma vie simple: Pointeur intelligent est tout simplement une classe qui surcharges -> et * les opérateurs. Ce qui signifie que votre objet sémantiquement ressemble à un pointeur, mais on peut faire plus frais de choses, y compris le comptage de référence, automatique destruction etc. shared_ptr et auto_ptr sont suffisants dans la plupart des cas, mais viennent avec leur propre ensemble de petites particularités..

34voto

markets Points 3598

Un pointeur intelligent, c'est comme un régulier (dactylographié) pointeur, comme "char*", sauf lorsque le pointeur lui-même est hors de portée, puis ce qu'il est supprimé. Vous pouvez l'utiliser comme vous le feriez d'un pointeur normal, en utilisant "->", mais pas si vous avez besoin d'une réelle pointeur vers les données. Pour cela, vous pouvez utiliser "&*ptr".

Il est utile pour:

  • Les objets qui doivent être alloués à nouveau, mais que vous aimeriez avoir la même durée de vie que quelque chose sur la pile. Si l'objet est affecté à un pointeur intelligent, alors ils seront supprimés lorsque le programme se termine que la fonction/bloc.

  • Les données des membres de classes, de sorte que lorsque l'objet est supprimé, la propriété des données est supprimé, sans aucun code spécial dans le destructeur (vous en aurez besoin pour être sûr que le destructeur est virtuel, ce qui est presque toujours une bonne chose à faire).

Vous pouvez ne pas vouloir utiliser un pointeur intelligent lorsque:

  • ... le pointeur ne devrait pas réellement les données... c'est à dire, lorsque vous êtes simplement en utilisant les données, mais vous voulez survivre à la fonction dans laquelle vous faites référence.
  • ... le pointeur intelligent n'est pas lui-même va être détruit à un certain point. Vous n'avez pas envie de s'asseoir dans la mémoire qui ne sera jamais détruit (comme dans un objet alloué dynamiquement, mais ne sera pas explicitement supprimé).
  • ... deux pointeurs intelligents peut-être les mêmes données. (Il y a, cependant, même le plus intelligent des pointeurs qui va gérer ça... ça s'appelle de comptage de référence.)

Voir aussi:

20voto

Chris Jester-Young Points 102876

La plupart des types de pointeurs intelligents poignée de jeter le pointeur vers l'objet pour vous. C'est très pratique car vous n'avez pas à penser à l'élimination des objets manuellement plus.

Le plus couramment utilisé des pointeurs intelligents sont std::tr1::shared_ptr (ou boost::shared_ptr), et, moins fréquemment, std::auto_ptr. Je recommande l'utilisation régulière d' shared_ptr.

shared_ptr est très polyvalent et traite avec une grande variété d'élimination des scénarios, y compris les cas où les objets doivent être "passés au-delà des limites de la DLL" (la commune cauchemar cas si différente libcs sont utilisés entre votre code et les Dll).

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