95 votes

shared_ptr magic :)

M. Lidström et moi a 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.

@Daniel: 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? – Armen Tsirunyan

@Armen: 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. – Daniel Lidström

@Daniel: je connais la 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 la Base et des dynamiques de type pointeur vers Dérivés, alors à moins que la Base a un destructeur virtuel, cela se traduira par un comportement indéfini. Corrigez-moi si je me trompe. – Armen Tsirunyan

@Armen: 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 agréable. – Daniel Lidström

Donc, jugde nous. Comment est-il possible (si elle est) afin de mettre en œuvre des shared_ptr sans exiger polymorphes classes ont destructeur virtuel? Merci d'avance

77voto

sellibitze Points 13607

Oui, il est possible de mettre en œuvre des shared_ptr de cette façon. Boost ne et la prochaine 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 (C++0x) pour cacher la réelle foncteur type. Pour faire de votre exemple de travail, nous avons besoin d'basé sur un modèle du constructeur:

template<class T>
class shared_ptr
{
public:
   ...
   template<class U>
   explicit shared_ptr(U* ptr);
   ...
};

Donc, si vous l'utilisez avec vos classes de Base et Dérivés ...

class Base {};
class Derived : public Base {};

int main() {
   shared_ptr<Base> sp (new Derived);
}

... basé sur un modèle du constructeur avec U=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.

30voto

ybungalobill Points 31467

Lorsque 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:

void DeleteDerived(Derived* d) { delete d; } // EDIT: no conversion needed.

shared_ptr<Base> p(new Derived, DeleteDerived);

p appellera DeleteDerived de détruire l'objet pointé. La mise en œuvre fait cela automatiquement.

17voto

Artyom Points 17387

Simplement,

shared_ptr utilise une fonction deleter spéciale créée par le constructeur qui utilise toujours le destructeur de l'objet donné et non le destructeur de Base. C'est un peu du travail avec la méta-programmation, mais cela fonctionne.

Quelque chose comme ca

 template<typename SomeType>
shared_ptr(SomeType *p)
{
   this->destroyer = destroyer_function<SomeType>(p);
   ...
}
 

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