Ce que le C++ Pointeur Intelligent Implémentations sont disponibles?
Les comparaisons, les avantages, les Inconvénients, et Quand les Utiliser?
C'est un spin-off à partir d'un la collecte des ordures fil où ce que je pensais était une simple réponse a généré beaucoup de commentaires au sujet de certains de pointeur intelligent implémentations il m'a donc semblé intéressant de commencer un nouveau post.
En fin de compte, la question est de savoir quelles sont les différentes implémentations de smart pointeurs en C++ là-bas et comment se comparent-ils? De simples avantages et des inconvénients ou des exceptions et de pièges à quelque chose que vous pourriez penser devrait fonctionner.
J'ai posté quelques implémentations que j'ai utilisé ou au moins dissimulés et a envisagé d'utiliser comme une réponse ci-dessous et de ma compréhension de leurs différences et les similitudes qui peuvent ne pas être précis à 100%, donc n'hésitez pas à la vérité ou me corriger au besoin.
L'objectif est de découvrir de nouveaux objets et des bibliothèques ou de corriger mon utilisation et la compréhension des implémentations existantes déjà largement en usage et à la fin de jouir d'un niveau de référence pour les autres.
- Je pense que cela devrait être ré-affiché comme une réponse à cette question, et la question d'une réelle question. Sinon, je sens les gens vont fermer ce que n'est pas "une vraie question".
- Il y a toutes sortes d'autres pointeurs intelligents, par exemple ATL smart pointeurs ou OpenSceneGraph est
osg::ref_ptr
. - Est-il question ici?
- "QObject et les classes dérivées, qui dans le framework Qt est tout" - pas tout à fait vrai. Qt a beaucoup de classes qui ne découle pas de QObject. La plupart d'entre eux sont implicitement partagé et rarement alloués sur le tas, si. Des exemples sont QString et QDom* les classes.
- Je pense que vous avez mal compris
std::auto_ptr
.std::auto_ptr_ref
est un détail de conception destd::auto_ptr
.std::auto_ptr
n'a rien à voir avec la collecte des ordures, c'est le principal objectif est précisément de permettre à l'exception sûr transfert de propriété, en particulier dans la fonction d'appel et de retour de la fonction des situations.std::unique_ptr
ne peut résoudre les "problèmes" que vous citez avec des conteneurs standard parce que le C++ a changé pour permettre une distinction entre les déplacer et copier et conteneurs standards ont changé pour profiter de cette. - Il est très probable l'utilisation prévue de
std::auto_ptr
n'était pas vraiment comme un pointeur intelligent qui pourrait expliquer la non-copiable la nature et le transfert de propriété lors de l'affectation. Je pense peut-être à l'échelle de l'abus et l'idée fausse de son usage prévu en partie conduit à la modification proposée. - Dans ce cas, quelle est votre définition de "pointeur intelligent"?
- Il s'agit d'un auto-destruction du pointeur.
- Il serait quelque chose le long des lignes de "un objet qui encapsule et contient un pointeur brut aux fins de la gestion de l'allocation et la désallocation de la mémoire en toute sécurité" ... j'ai édité avec un texte de présentation et un lien vers un article que j'ai lu lorsque l'on cherche précisément pourquoi
std::auto_ptr
ne pouvait pas être utilisé en toute sécurité dans certains cas. - Par définition, pas beaucoup de votre cité objets sont des pointeurs intelligents que quelques-uns d'entre eux de gérer l'allocation. - Je censé
shared_ptr
compte carmake_shared
est une partie de son interface, mais votre définition semble plus proche de ce que j'appellerais un "pimpl" classe. - Vous dites que vous n'êtes pas un expert dans les pointeurs intelligents, mais que votre résumé est assez exhaustive et correcte (sauf pour les mineurs ergoter sur
auto_ptr_ref
être un détail de l'implémentation). Encore, je suis d'accord que vous devez poster cela comme une réponse et de reformuler la question à une question réelle. Cela peut alors servir de référence future. - Je suppose que votre droit, si vous voulez être argumenté que la définition n'était pas le même
reset()
méthodes n'appelez pasnew
pour vous si je dois supprimer "affectation et" ... même si je suis sûr que quelqu'un a probablement mis en place quelque chose comme ça avant. - Ma définition de pointeur intelligent est probablement beaucoup plus ample que la vôtre, alors. Je considère
auto_ptr
être un pointeur intelligent donc, quand vous avez dit que "l'utilisation prévue destd::auto_ptr
n'était pas vraiment comme un pointeur intelligent" je voulais juste préciser exactement ce que vous voulez dire par un pointeur intelligent. Je ne cherche pas à être pointilleux ou argumentatif, juste effacer. - Vote pour l'ouvrir. La question est clairement indiqué: "en fin de compte, la question est de savoir quelles sont les différentes implémentations de smart pointeurs en C++ là-bas et comment se comparent-ils?". AINSI a été conçu pour permettre l'auto-répond à des questions au bénéfice de la communauté. De discuter du fond, les forces et les faiblesses des différents pointeurs sera utile aux gens, ce qui est le but ultime.
- A l'origine, il était dans la question, je n'ai pas réussi à modifier la structure actuelle assez vite 😉
- malheureusement, c'est l'un des principaux problèmes que j'ai avec. Les Questions sont voté fermé trop vite, surtout quand il ya une réelle possibilité de récupérer assez facilement.
- C'était impressionnant de 5 minutes de marge, mais je ne peux pas me plaindre. Une très grande attention aux détails les plus infimes est à la fois une bonne et une mauvaise caractéristique de programmeurs.
- d'accord, mais à une tentative de refactoring doit être faite avant de jeter un morceau de code =P
- "Les comparaisons, les avantages, les Inconvénients, et Quand les Utiliser?" genre de question conduit à toutes sortes de subjectif des réponses (en plus c'est un auto répondu à la question...) je pense vraiment que ce devrait être la reformuler dans quelque chose comme "Qui sont les Pointeurs Intelligents implémentations en C++?" et chacun doit être dans un coin de la réponse.
- A voté pour le ré-ouvrir, maintenant que ceci est une vraie question. Ce pourrait même être la peine de marquage comme
c++-faq
. Je le ferais moi-même, mais je ne suis pas sûr de les 5 balises à remplacer. @Josh: Même si des questions peuvent être fermées rapidement, comme vous l'avez remarqué, ils peuvent aussi être ré-ouvert. Pas de réel problème ici. La question a été modifié pour être une réelle question, et il est maintenant possible d'y répondre. Ainsi, il a été ré-ouvert. - J'ai édité la question. Je vais laisser ma réponse que c'est parce qu'il semble excessif de poster une auto-réponse pour chaque mise en œuvre.
- Accepter puisque personne d'autre ne semble avoir d'autres implémentations d'ajouter ou de corrections.
- Ajouté
c++-faq
tag, et a supprimé lesc++-11
, comme il est en train de devenir le nouveauc++
bientôt... je l'espère. - Connexes: qu'est Ce qu'un pointeur intelligent et quand dois-je utiliser?
Vous devez vous connecter pour publier un commentaire.
C++03
std::auto_ptr
- Peut-être l'un des originaux, il a souffert de la première ébauche du syndrome de seulement fournir limité la collecte des ordures installations. Le premier inconvénient étant qu'il appelledelete
lors de la destruction en les rendant inacceptable pour la tenue de tableau d'objets alloués (new[]
). Il prend en charge le pointeur de façon à ce que deux auto pointeurs ne devrait pas contenir le même objet. L'attribution de transfert de propriété et de réinitialiser le rvalue auto pointeur vers un pointeur null. Ce qui conduit à peut-être le pire inconvénient; ils ne peuvent pas être utilisés dans les conteneurs STL en raison de cette incapacité à être copié. Le coup de grâce à toute utilisation, c'est qu'ils sont prévus pour être obsolète dans le prochain standard de C++.std::auto_ptr_ref
- Ce n'est pas un pointeur intelligent c'est en fait un détail de conception utilisé en conjonction avecstd::auto_ptr
de permettre la copie et l'affectation dans certaines situations. Plus précisément, il peut être utilisé pour convertir un non-conststd::auto_ptr
à un lvalue à l'aide de la Colvin-Gibbons truc aussi connu comme un constructeur de déplacement de transfert de propriété.Au contraire peut-être
std::auto_ptr
n'était pas vraiment destiné à être utilisé comme un objectif général de pointeur intelligent automatique de collecte des ordures. La plupart de ma compréhension limitée et hypothèses sont fondées sur Herb Sutter de l'Utilisation Efficace de l'auto_ptr et je ne l'utilise régulièrement, mais pas toujours dans le plus optimisé façon.C++11
std::unique_ptr
- C'est notre ami qui remplacerastd::auto_ptr
il sera tout à fait similaire, sauf avec la touche améliorations en vue de corriger les lacunes destd::auto_ptr
aime travailler avec des tableaux, lvalue protection via un constructeur de copie privée, utilisable avec des conteneurs STL et les algorithmes, etc. Puisque c'est la surcharge de performances et de mémoire sont limitées, est un candidat idéal pour remplacer, ou peut-être plus justement décrite comme la propriété, la crue des pointeurs. Comme le "uniques" implique qu'il n'y est qu'un seul propriétaire de l'aiguille, tout comme le précédentstd::auto_ptr
.std::shared_ptr
- Je crois que c'est basé sur TR1 etboost::shared_ptr
mais amélioré pour inclure d'aliasing et de l'arithmétique des pointeurs ainsi. En bref, il enroule une référence compté smart pointeur sur un objet alloué dynamiquement. Comme le "partage" implique le pointeur peut être détenue par plus d'un pointeur partagé lors de la dernière référence de la dernière pointeur partagé est hors de portée alors l'objet sera supprimé de façon appropriée. Ce sont aussi des threads et peut gérer incomplète types dans la plupart des cas.std::make_shared
peut être utilisé efficacement à la construction d'unstd::shared_ptr
avec un tas de répartition à l'aide de la valeur par défaut de l'allocateur.std::weak
- Même basé sur TR1 etboost::weak_ptr
. C'est une référence à un objet appartenant à unstd::shared_ptr
et ne seront donc pas empêcher la suppression de l'objet, si lestd::shared_ptr
référence compteur tombe à zéro. Afin d'obtenir l'accès à l'pointeur brut, vous devez d'abord accéder à lastd::shared_ptr
en appelantlock
qui sera de retour un videstd::shared_ptr
si le pointeur de la propriété a expiré et déjà été détruite. Ceci est principalement utile pour éviter indéfinie de la pendaison des comptes de référence lors de l'utilisation de plusieurs pointeurs intelligents.Boost
boost::shared_ptr
- Probablement le plus facile à utiliser dans la plupart des divers scénarios (STL, PIMPL, RAII, etc) c'est partagé référencé comptés pointeur intelligent. J'ai entendu beaucoup de plaintes au sujet de la performance et les frais généraux, dans certaines situations, mais je dois l'avoir ignoré, parce que je ne me souviens pas de ce que l'argument. Apparemment, il était assez populaire pour devenir une future norme C++ objet et pas d'inconvénients sur la norme concernant les pointeurs intelligents viennent à l'esprit.boost::weak
, Comme pour la précédente description destd::weak_ptr
, à partir de cette mise en œuvre, ce qui permet à un non-propriétaire de référence à unboost::shared_ptr
. Vous n'est pas surprenant appellock()
pour accéder à la "forte" pointeur partagé et doit vérifier pour s'assurer qu'il est valide qu'il pourrait avoir déjà été détruit. Assurez-vous juste de ne pas stocker le pointeur partagé retourné et le laisser aller hors de portée dès que vous avez terminé avec elle, sinon vous êtes de retour au cours du cycle de référence de problème où votre nombre de références se bloque et les objets ne seront pas détruits.boost::scoped_ptr
- C'est un simple pointeur intelligent de la classe avec peu de surcharge probablement conçues pour une alternative performante à laboost::shared_ptr
quand utilisable. C'est comparable àstd::auto_ptr
surtout dans le fait qu'il ne peut pas être utilisé sans danger comme un élément d'un conteneur STL ou avec plusieurs pointeurs vers le même objet.boost::intrusive_ptr
- Je n'ai jamais utilisé ça, mais à partir de ma compréhension, il est conçu pour être utilisé lors de la création de votre propre pointeur intelligent compatible classes. Vous avez besoin de mettre en œuvre le comptage de référence vous-même, vous aurez également besoin de mettre en œuvre quelques méthodes si vous voulez que votre classe soit générique, de plus vous auriez à mettre en place votre propre fil de sécurité. Sur le côté positif, c'est probablement ce qui vous donne le plus personnalisé manière de sélectionner et de choisir exactement comment ou combien peu "intelligence" vous voulez.intrusive_ptr
est généralement plus efficace queshared_ptr
car il vous permet d'avoir un seul tas de répartition par objet. (merci Arvid)boost::shared_array
- C'est unboost::shared_ptr
pour les tableaux. Fondamentalementnew []
,operator[]
, et bien sûrdelete []
sont cuites. Ceci peut être utilisé dans des conteneurs STL et pour autant que je sais, tout neboost:shared_ptr
n'bien que vous ne pouvez pas utiliserboost::weak_ptr
avec ces. Vous pouvez, toutefois, vous pouvez également utiliser unboost::shared_ptr<std::vector<>>
pour des fonctionnalités similaires et de retrouver la capacité à utiliserboost::weak_ptr
pour les références.boost::scoped_array
- C'est unboost::scoped_ptr
pour les tableaux. Comme avecboost::shared_array
tout le nécessaire de la matrice de la bonté est cuit. Celui-ci est non-copiable et ne peut donc pas être utilisé dans des conteneurs STL. J'ai trouvé presque n'importe où vous vous trouvez vouloir utiliser cette fonction, vous probablement pouvez simplement utiliserstd::vector
. Je n'ai jamais déterminé qui est vraiment le plus rapide ou a moins de frais généraux, mais cette étendue de tableau semble beaucoup moins impliqué qu'un vecteur STL. Lorsque vous souhaitez garder l'allocation sur la pile envisagerboost::array
à la place.Qt
QPointer
- Introduit dans Qt 4.0 c'est un "faible" pointeur intelligent qui fonctionne uniquement avecQObject
et les classes dérivées, qui dans le framework Qt est presque tout ce qui n'est pas vraiment une limitation. Cependant il y a des limites à savoir qu'il ne fournit pas un "fort" pointeur et bien que vous pouvez vérifier si l'objet sous-jacent est valide avecisNull()
vous pourriez trouver votre objet détruit juste après que vous passez vérifier en particulier dans les environnements multi-threadés. Qt considèrent que c'obsolète, je crois.QSharedDataPointer
- C'est une "forte" pointeur intelligent potentiellement comparable àboost::intrusive_ptr
bien qu'il a une certaine construit dans le thread de la sécurité, mais cela vous oblige à inclure une référence méthodes de comptage (ref
etderef
) où vous pouvez faire en sous-classementQSharedData
. Comme avec beaucoup de Qt les objets sont utilisés au mieux par le biais de suffisamment de l'héritage et sous-classement, tout semble être la conception.QExplicitlySharedDataPointer
- Très semblable àQSharedDataPointer
sauf qu'il n'est pas implicitement appeldetach()
. J'appellerais cette version 2.0 deQSharedDataPointer
que cette légère augmentation de contrôler exactement quand se détacher au bout de la référence compteur tombe à zéro n'est pas particulièrement en valeur un tout nouvel objet.QSharedPointer
- Atomique de comptage de référence, thread-safe, partageable pointeur personnalisé supprime (matrice de soutien), des sons comme tout un pointeur intelligent devrait être. C'est ce que j'ai surtout l'utiliser comme un pointeur intelligent en Qt et je trouve qu'il comparable avecboost:shared_ptr
bien que sans doute beaucoup plus de frais généraux comme le nombre d'objets dans Qt.QWeakPointer
- Avez-vous le sentiment d'un motif récurrent? Tout commestd::weak_ptr
etboost::weak_ptr
il est utilisé en conjonction avecQSharedPointer
lorsque vous avez besoin de références entre les deux pointeurs intelligents qui pourrait entraîner vos objets de façon à ne jamais être supprimé.QScopedPointer
- Ce nom devrait également paraître familier et était en réalité en réalité basée surboost::scoped_ptr
à la différence de l'intervalle Qt versions du partage et de la faiblesse des pointeurs. Il fonctionne pour fournir un seul propriétaire pointeur intelligent sans les frais deQSharedPointer
qui le rend plus adapté pour la compatibilité, l'exception code de sécurité, et toutes les choses que vous pouvez utiliserstd::auto_ptr
ouboost::scoped_ptr
pour.intrusive_ptr
est généralement plus efficace queshared_ptr
, car il vous permet d'avoir un seul tas de répartition par objet.shared_ptr
sera dans le cas général d'allouer un des petits tas d'objets pour les compteurs de référence.std::make_shared
peut être utilisé pour obtenir le meilleur des deux mondes.shared_ptr
avec une seule allocation de tas.shared_ptr
s? (Sans compter la résolution cyclique références)shared_ptr
mais vous n'en voulez pas à placer tous les pointeurs. Vous devez également vous assurer de raw pointeurs de référence à la même mémoire incrémenter la ref nombre en les enveloppant dansshared_ptr
ainsi que de supprimer tout le code de suppression manuelle de la mémoire détenue par leshared_ptr
. Fondamentalement, n'importe quand vous utiliseznew
, vous pouvez le faire avec un pointeur intelligent à la place.std::auto_ptr<>
est qu'il ne peut pas être utilisé dans les en-têtes à l'avant-déclaré types, ce qui signifie que vous ne pouvez pas l'utiliser pour le Pimpl idiome. En revancheshared_ptr<>
(parmi d'autres) peut être utilisé de cette façon. Un inconvénient deshared_ptr
cependant, c'est que c'est tout ou rien: une fois que vous passez un pointeur brut en elle, alors vous pouvez ne jamais renoncer à la propriété de nouveau.nullptr
bien que je n'ai jamais essayé comme d'habitude le but de l'utilisation d'un pointeur intelligent est parce que je veux posséder le pointeur brut.std::auto_ptr
de l'avant, a déclaré types. Je l'ai fait et jamais eu de problèmes avec des fuites de mémoire. En fait Pimpl est le parfait cas d'utilisation pourstd::auto_ptr
.shared_ptr
utilise un truc avec une fonction virtuelle pour contourner ce problème.Il est également Loki qui met en oeuvre une politique basée sur des pointeurs intelligents.
Autres références sur la politique basée sur des pointeurs intelligents, aborder le problème du manque de soutien de la vide de la base de l'optimisation de l'héritage multiple par de nombreux compilateurs:
En plus de celles indiquées, il y a quelques axés sur la sécurité trop:
SaferCPlusPlus
mse::TRefCountingPointer
est un comptage de référence de pointeur intelligent commestd::shared_ptr
. La différence étant quemse::TRefCountingPointer
est plus sûr, plus petit et plus rapide, mais n'a pas de fil mécanisme de sécurité. Et il s'agit de "not null" et "fixe" (non-reciblage) versions qui peuvent être raisonnablement supposer toujours être orientée vers un valablement objet alloué. Donc en gros, si votre objet cible est partagé entre les threads asynchrones ensuite utiliserstd::shared_ptr
, sinonmse::TRefCountingPointer
est plus optimal.mse::TScopeOwnerPointer
est similaire àboost::scoped_ptr
, mais fonctionne en conjonction avecmse::TScopeFixedPointer
dans une "forte-faible" pointeur de la relation de genre commestd::shared_ptr
etstd::weak_ptr
.mse::TScopeFixedPointer
points pour les objets qui sont allouées sur la pile, ou dont le "posséder" le pointeur est alloué sur la pile. Il est (volontairement) limitée dans ses fonctionnalités afin d'améliorer le temps de compilation de la sécurité sans runtime coût. La question de la "portée" des pointeurs est essentiellement à identifier un ensemble de circonstances qui sont simples et déterministes assez que personne (à l'exécution) des mécanismes de sécurité sont nécessaires.mse::TRegisteredPointer
se comporte comme un pointeur brut, sauf que sa valeur est automatiquement définie sur null_ptr lorsque l'objet cible est détruite. Il peut être utilisé comme un remplacement général pour les matières premières, les pointeurs dans la plupart des situations. Comme un pointeur brut, il n'a pas intrinsèque de la sécurité des threads. Mais en contrepartie, il n'a pas de problème de ciblage d'objets alloués sur la pile (et l'obtention de la performance correspondante des prestations). Lorsque le temps d'exécution de contrôles sont activés, ce pointeur est à l'abri de l'accès mémoire invalide. Parce quemse::TRegisteredPointer
a le même comportement qu'un pointeur brut lors du pointage d'objets, il peut être "désactivé" (automatiquement remplacé par le correspondant pointeur brut) avec une directive de compilation, lui permettant d'être utilisé pour aider à repérer les bugs dans le debug/test/beta modes tout en occasionnant pas de frais généraux en mode release.Ici est un article qui décrit pourquoi et comment les utiliser. (Remarque, shameless plug.)