C ++ est tout au sujet de la propriété de la mémoire - aka sémantique de propriété .
Il est de la responsabilité du propriétaire d'un morceau de mémoire allouée dynamiquement de libérer cette mémoire. La question est donc de savoir à qui appartient la mémoire.
En C ++, la propriété est documentée par le type dans lequel un pointeur brut est enveloppé.Par conséquent, dans un bon programme C ++ (IMO), il est très rare ( rare , pas jamais ) de voir des pointeurs bruts passés (car les pointeurs bruts n'ont pas de propriété déduite, nous pouvons donc ne pas dire à qui appartient la mémoire et donc sans une lecture attentive de la documentation, vous ne pouvez pas dire qui est responsable de la propriété).
Inversement, il est rare de voir des pointeurs bruts stockés dans une classe, chaque pointeur brut est stocké dans son propre wrapper de pointeur intelligent. ( NB: si vous ne possédez pas un objet, vous ne devriez pas le stocker car vous ne pouvez pas savoir quand il sortira de sa portée et sera détruit.)
Donc la question:
- Quel type de sémantique de propriété les gens ont-ils rencontrés?
- Quelles classes standard sont utilisées pour implémenter cette sémantique?
- Dans quelles situations les trouvez-vous utiles?
Permet de conserver 1 type de propriété sémantique par réponse afin qu'ils puissent être votés individuellement.
Résumé:
Conceptuellement, les pointeurs intelligents sont simples et une mise en œuvre naïve est facile. J'ai vu de nombreuses tentatives d'implémentation, mais elles sont invariablement interrompues d'une manière qui n'est pas évidente pour une utilisation occasionnelle et des exemples. Ainsi, je recommande de toujours utiliser des pointeurs intelligents bien testés à partir d'une bibliothèque plutôt que de lancer le vôtre. std::auto_ptr
ou l'un des pointeurs intelligents Boost semble couvrir tous mes besoins.
std::auto_ptr<T>
:
Une seule personne possède l'objet. Le transfert de propriété est autorisé.
Utilisation: Cela vous permet de définir des interfaces qui montrent le transfert explicite de propriété.
boost::scoped_ptr<T>
Une seule personne possède l'objet. Le transfert de propriété n'est PAS autorisé.
Utilisation: utilisé pour montrer la propriété explicite. L'objet sera détruit par le destructeur ou lors d'une réinitialisation explicite.
boost::shared_ptr<T>
( std::tr1::shared_ptr<T>
)
Propriété multiple. Il s'agit d'un simple pointeur compté par référence. Lorsque le nombre de références atteint zéro, l'objet est détruit.
Utilisation: lorsqu'un objet peut avoir plusieurs owers avec une durée de vie qui ne peut pas être déterminée au moment de la compilation.
boost::weak_ptr<T>
:
Utilisé avec shared_ptr<T>
dans les situations où un cycle de pointeurs peut se produire.
Utilisation: Utilisé pour empêcher les cycles de conserver des objets lorsque seul le cycle gère un refcount partagé.
la source
In C++ ownership is documented by the type a RAW pointer is wrapped inside thus in a good (IMO)
Cela peut-il être reformulé? Je ne comprends pas du tout.In C++ ownership is documented by the type a RAW pointer is wrapped inside thus in a good C++ program it is very rare to see RAW pointers passed around
. Les pointeurs RAW n'ont pas de sémantique de propriété. Si vous ne connaissez pas le propriétaire, vous ne savez pas qui est responsable de la suppression de l'objet.Il existe plusieurs classes standard qui sont utilisées pour encapsuler les pointeurs (std :: shared_ptr, std :: unique_ptr etc) qui définissent la propriété et donc définir qui est responsable de la suppression du pointeur.Réponses:
Pour moi, ces 3 types couvrent la plupart de mes besoins:
shared_ptr
- comptage de référence, désallocation lorsque le compteur atteint zéroweak_ptr
- comme ci-dessus, mais c'est un 'esclave' pour unshared_ptr
, impossible de désallouerauto_ptr
- lorsque la création et la désallocation se produisent à l'intérieur de la même fonction, ou lorsque l'objet doit être considéré comme un seul propriétaire. Lorsque vous affectez un pointeur à un autre, le second «vole» l'objet du premier.J'ai ma propre implémentation pour ceux-ci, mais ils sont également disponibles au format
Boost
.Je passe toujours des objets par référence (dans la
const
mesure du possible), dans ce cas, la méthode appelée doit supposer que l'objet n'est vivant que pendant le moment de l'appel.J'utilise un autre type de pointeur que j'appelle hub_ptr . C'est lorsque vous avez un objet qui doit être accessible à partir d'objets imbriqués (généralement en tant que classe de base virtuelle). Cela pourrait être résolu en leur passant un
weak_ptr
, mais cela n'a passhared_ptr
de lui-même. Comme il sait que ces objets ne vivraient pas plus longtemps que lui, il leur passe un hub_ptr (c'est juste un wrapper de modèle vers un pointeur normal).la source
noncopyable
et que la propriété ne peut être transférée.Modèle C ++ simple
Dans la plupart des modules que j'ai vus, par défaut, il était supposé que la réception de pointeurs ne recevait pas la propriété. En fait, les fonctions / méthodes abandonnant la propriété d'un pointeur étaient à la fois très rares et exprimaient explicitement ce fait dans leur documentation.
Ce modèle suppose que l'utilisateur n'est propriétaire que de ce qu'il alloue explicitement . Tout le reste est automatiquement éliminé (à la sortie de la portée ou via RAII). Il s'agit d'un modèle de type C, étendu par le fait que la plupart des pointeurs appartiennent à des objets qui les désalloueront automatiquement ou en cas de besoin (lors de la destruction desdits objets, principalement), et que la durée de vie des objets est prévisible (RAII est votre ami, encore).
Dans ce modèle, les pointeurs bruts circulent librement et ne sont généralement pas dangereux (mais si le développeur est suffisamment intelligent, il utilisera des références à la place chaque fois que possible).
Modèle C ++ pointé intelligent
Dans un code rempli de pointeurs intelligents, l'utilisateur peut espérer ignorer la durée de vie des objets. Le propriétaire n'est jamais le code utilisateur: c'est le pointeur intelligent lui-même (RAII, encore une fois). Le problème est que les références circulaires mélangées à des pointeurs intelligents comptés par référence peuvent être mortelles , vous devez donc gérer à la fois des pointeurs partagés et des pointeurs faibles. Vous avez donc toujours la propriété à considérer (le pointeur faible pourrait bien ne pointer vers rien, même si son avantage par rapport au pointeur brut est qu'il peut vous le dire).
Conclusion
Peu importe les modèles que je décris, à moins exception, la réception d' un pointeur est pas Récipiendaire de sa propriété et il est encore très important de savoir qui est propriétaire qui . Même pour le code C ++ utilisant fortement des références et / ou des pointeurs intelligents.
la source
Je n'ai pas de propriété partagée. Si vous le faites, assurez-vous que ce n'est qu'avec du code que vous ne contrôlez pas.
Cela résout 100% des problèmes, car cela vous oblige à comprendre comment tout interagit.
la source
Lorsqu'une ressource est partagée entre plusieurs objets. Le boost shared_ptr utilise le comptage de références pour s'assurer que la ressource est désallouée lorsque tout le monde est terminé.
la source
std::tr1::shared_ptr<Blah>
est souvent votre meilleur pari.la source
De boost, il y a aussi le conteneur de pointeur bibliothèque de . Ceux-ci sont un peu plus efficaces et plus faciles à utiliser qu'un conteneur standard de pointeurs intelligents, si vous n'utilisez les objets que dans le contexte de leur conteneur.
Sous Windows, il existe les pointeurs COM (IUnknown, IDispatch et amis) et divers pointeurs intelligents pour les gérer (par exemple, le CComPtr de l'ATL et les pointeurs intelligents générés automatiquement par l'instruction "import" dans Visual Studio basé sur la classe _com_ptr ).
la source
Lorsque vous avez besoin d'allouer de la mémoire dynamiquement mais que vous voulez être sûr qu'elle est désallouée à chaque point de sortie du bloc.
Je trouve cela utile car il peut facilement être remis en place et relâché sans jamais avoir à se soucier d'une fuite
la source
Je ne pense pas avoir jamais été en mesure de partager la propriété de ma conception. En fait, du haut de ma tête, le seul cas valable auquel je puisse penser est le modèle Flyweight.
la source
yasper :: ptr est une alternative légère, semblable à boost :: shared_ptr. Cela fonctionne bien dans mon (pour l'instant) petit projet.
Dans la page Web à http://yasper.sourceforge.net/, il est décrit comme suit:
la source
Il existe une autre forme fréquemment utilisée de propriétaire unique transférable, et elle est préférable
auto_ptr
car elle évite les problèmes causés parauto_ptr
la corruption insensée de la sémantique des affectations.Je parle de nul autre que
swap
. Tout type avec uneswap
fonction appropriée peut être conçu comme une référence intelligente à un contenu, qu'il possède jusqu'à ce que la propriété soit transférée à une autre instance du même type, en les échangeant. Chaque instance conserve son identité mais est liée à un nouveau contenu. C'est comme une référence rebindable en toute sécurité.(C'est une référence intelligente plutôt qu'un pointeur intelligent, car vous n'avez pas à le déréférencer explicitement pour accéder au contenu.)
Cela signifie que auto_ptr devient moins nécessaire - il n'est nécessaire que pour combler les lacunes là où les types n'ont pas une bonne
swap
fonction. Mais tous les conteneurs std le font.la source
Lorsque le créateur de l'objet veut céder explicitement la propriété à quelqu'un d'autre. C'est aussi une façon de documenter dans le code que je vous donne et je ne le suit plus, alors assurez-vous de le supprimer lorsque vous avez terminé.
la source