shared_ptr magique :)
M. Lidström et j'ai eu un argument 🙂
M. Lidström est qu'une construction shared_ptr<Base> p(new Derived);
ne nécessite pas de Base pour avoir un destructeur virtuel:
Armen Tsirunyan: "Vraiment? Sera le shared_ptr nettoyer correctement? Pourriez-vous s'il vous plaît dans ce cas, de démontrer comment cet effet pourrait être mis en œuvre?"
Daniel Lidström: "La shared_ptr utilise sa propre destructeur pour supprimer le Béton instance. Ceci est connu comme RAII dans le C++ de la communauté. Mon conseil est que vous apprenez tout ce que vous pouvez au sujet de RAII. Il fera de votre codage C++ donc beaucoup plus facile lorsque vous utilisez RAII dans toutes les situations."
Armen Tsirunyan: "je connais les RAII, et je sais aussi que, finalement, les shared_ptr destructeur peut supprimer le nom d'px lorsque pn atteint 0. Mais si px avait statique de type pointeur vers
Base
et dynamique de type pointeur versDerived
, alors à moins queBase
a un destructeur virtuel, cela se traduira par un comportement indéfini. Corrigez-moi si je me trompe."Daniel Lidström: "La shared_ptr sait le type statique est en Béton. Il le sait depuis que j'ai passé dans son constructeur! Semble un peu comme de la magie, mais je peux vous assurer qu'il est voulu par la conception et extrêmement gentil."
Donc, de nous juger. Comment est-il possible (si elle est) afin de mettre en œuvre shared_ptr sans exiger polymorphes classes ont destructeur virtuel?
Merci d'avance
Une autre chose intéressante est que
shared_ptr<void> p(new Derived)
détruira aussi les Derived
objet par c'est destructeur, peu importe si c'est virtual
ou pas.Génial façon de poser une question 🙂
Même si shared_ptr qui permet cela, c'est un très mauvaise idée pour la conception d'une classe de base sans virtuel dtor. Daniel commentaires à propos de RAII sont fausses, il n'a rien à voir avec cela—mais le prix de la conversation ressemble à une simple erreur de communication (et de l'hypothèse erronée de la façon dont shared_ptr œuvres).
Pas RAII, mais plutôt de type efface le destructeur. Vous devez être prudent, parce que
shared_ptr<T>( (T*)new U() )
où struct U:T
de ne pas faire la bonne chose (et cela peut être fait indirectement facilement, comme une fonction qui prend un T*
et est passée à une U*
)OriginalL'auteur Armen Tsirunyan | 2010-10-10
Vous devez vous connecter pour publier un commentaire.
Oui, il est possible de mettre en œuvre des shared_ptr de cette façon. Boost et le C++11 norme exige également ce comportement. Pour plus de flexibilité shared_ptr gère plus que juste un compteur de référence. Un soi-disant deleter est généralement mis dans le même bloc de mémoire qui contient également les compteurs de référence. Mais la partie la plus amusante est que le type de ce deleter ne fait pas partie de la shared_ptr type. Ceci est appelé "type effacement" et est fondamentalement la même technique utilisée pour la mise en œuvre de la "fonctions polymorphes" boost::function ou std::function pour cacher la réelle foncteur type. Pour faire de votre exemple de travail, nous avons besoin d'basé sur un modèle constructeur:
Donc, si vous l'utilisez avec vos classes de Base et Dérivés ...
... basé sur un modèle du constructeur avec Y=Dérivée est utilisée pour construire les shared_ptr objet. Le constructeur a ainsi la possibilité de créer des deleter objet et de compteurs de référence et stocke un pointeur vers ce bloc de contrôle de données par le membre. Si le compteur atteint zéro, créé précédemment et Dérivés de la conscience deleter sera utilisé pour disposer de l'objet.
Le C++11 standard a dire au sujet de ce constructeur (20.7.2.2.1):
Et pour le destructeur (20.7.2.2.2):
(les italiques sont de l'utilisation de caractères gras est de moi).
the upcoming standard also requires this behaviour
: (a) de la norme et (b) pouvez-vous veuillez donner une référence (de la norme)?OriginalL'auteur sellibitze
Quand shared_ptr est créé, il stocke une deleter objet à l'intérieur de lui-même. Cet objet est appelé lorsque le shared_ptr est sur le point de libérer le relevé des ressources. Puisque vous savez comment détruire la ressource à l'endroit de la construction, vous pouvez utiliser shared_ptr incomplète types. La personne qui a créé le shared_ptr stocké une bonne deleter.
Par exemple, vous pouvez créer un deleter:
p appellera DeleteDerived de détruire l'objet pointé. La mise en œuvre fait automatiquement.
shared_ptr
comme un attribut.OriginalL'auteur ybungalobill
Simplement,
shared_ptr
utilise spécial deleter fonction qui est créé par un constructeur qui utilise toujoursle destructeur de l'objet donné et de ne pas le destructeur de Base, c'est un peu de travail avec le modèle de méta-programmation, mais il fonctionne.
Quelque chose comme ça
Tsirunyan Vous devriez avoir jeté un coup d'oeil dans la description de la conception de la shared_ptr avant de commencer la discusson. Cette "capture de la deleter" est l'une des caractéristiques essentielles de shared_ptr...
Je suis d'accord avec vous. D'autre part, je crois que cette discussion a été utile non seulement pour moi, mais aussi pour d'autres personnes qui ne savent pas ce fait sur le shared_ptr. Donc je suppose que ce n'était pas un grand péché pour lancer ce sujet de toute façon 🙂
Bien sûr que non. Plutôt, vous avez fait un bon travail en pointant vers le présent vraiment très très caractéristique importante de shared_ptr<T> qui est souvent supervisé même par des développeurs c++.
OriginalL'auteur Artyom