49 votes

Reviver objet de destructeur en C ++?

Avertissement: je sais que c'est un mauvais design, je suis tout simplement en posant la question, par curiosité, pour essayer d'obtenir une connaissance plus approfondie de la façon dont le destructeur fonctionne en C++.

En C#, on peut écrire: GC.KeepAlive(ce) dans le destructeur d'une classe (voir modifier ci-dessous), et qui signifie que l'objet sera toujours vivant dans la mémoire, même après le destructeur de l'appel est terminé.

La conception de C++ permettre la relance d'un objet, le destructeur similaire à C# à l'algorithme décrit ci-dessus?

Edit: Comme l'a souligné une réponse ci-dessous, GC.ReRegisterForFinalize() est plus étroitement liée à la question de GC.KeepAlive(ce).

100voto

Sam Varshavchik Points 2563

La réponse courte est non. C ++ n'utilise pas de garbage collection, comme Java ou C #. Lorsqu'un objet est détruit, il est immédiatement détruit. Parti pour de bon. Rejoint la chorale invisible. Epouvantable pour les fjords, etc ...

Cela dit, C ++ vous permet d'implémenter un allocateur personnalisé pour vos classes. Si vous le souhaitez, vous pouvez écrire vos propres fonctions personnalisées d'allocation de mémoire et de désallocation, qui implémentent les fonctionnalités de votre choix.

53voto

NineBerry Points 923

Vous êtes réellement en dénaturant ce que GC.KeepAlive n'en .NET. Il n'est pas utilisé dans un destructeur d'un objet à garder cet objet d'être détruits -- en fait, GC.KeepAlive() est vide et n'a pas de mise en œuvre. Voir la .NET code source ici.

Il permet de s'assurer que l'objet passé en paramètre n'est pas nettoyée avant l'appel à GC.KeepAlive se passe. L'objet passé en KeepAlive comme un paramètre peut être nettoyée immédiatement après l'appel à GC.KeepAlive. Depuis KeepAlive n'a pas de réelle mise en œuvre, ce qui se passe purement basée sur le fait que le compilateur doit conserver une référence à l'objet passé en paramètre à l' KeepAlive. Toute autre fonction (qui n'est pas incorporé par le compilateur ou de l'exécution) de prendre l'objet en tant que paramètre peut être utilisé à la place.

8voto

jdlugosz Points 96

Voici une idée:

C* gPhoenix= nullptr;

C::~C ()
{
gPhoenix= new C (*this);  // note: loses any further-derived class ("slice")
}

Maintenant, si les objets concernés (bases ou les membres) ont vraiment destructeurs que faire quelque chose, cela se heurte à un problème si vous delete gPhoenix; de sorte que vous aurez besoin de plus de mécanismes élaborés en fonction de ce que c'est vraiment essayer de l'accomplir. Mais vous n'avez pas de réels objectifs, juste curieux d'exploration, afin de souligner ce point devrait suffire.

Lorsque le corps du destructeur est appelé, l'objet est toujours parfaitement bien. Il semble parfaitement vital et normal que de vous faire membre normal des appels de fonctions dans le destructeur.

La mémoire de posséder l'objet sera remis en état, de sorte que vous ne pouvez pas rester en place. Et après avoir quitté le corps, d'autres à la destruction a lieu automatiquement et ne peut pas être entravé. Mais, vous pouvez dupliquer l'objet avant que cela arrive.

6voto

Theraot Points 5174

Comme cela a déjà été souligné, GC.KeepAlive ne le fait pas.

Aussi longtemps que .NET va, il est possible de ressusciter à partir de l'outil de finalisation à l'aide de GC.ReRegisterForFinalize, vous pouvez toujours obtenir une référence à elle si vous avez un WeakReference ou GCHandle suivi de la ressurection, ou simplement donnez this de quelque chose en dehors de la classe. Cela abandonner à la destruction.

C'est un vieux truc pour détecter la collecte des ordures .NET 2.0 n'est plus pertinent, mais fonctionne encore (un peu, la collecte des ordures peut maintenant être partielle, et de faire en parallèle avec d'autres threads).

L'accent devrait être mis sur le fait que sur .NET vous utilisez un outil de finalisation, qui s'exécute avant la destruction, et ne peut l'empêcher. Ainsi, s'il est techniquement correcte, que vous ne pouvez pas récupérer un objet après la destruction dans n'importe quelle langue , vous pouvez obtenir près le comportement que vous décrivez .NET, sauf à l'aide d' GC.ReRegisterForFinalize à la place.


Sur le C++, vous avez déjà donné la réponse correcte.

4voto

Sorin Points 1606

Ce n'est pas possible dans toutes les langues.

Votre compréhension est un peu hors. GC.KeepAlive marquera l'objet ne peuvent être recouvrés par le garbage collector. Cela permettra d'éviter la collecte des ordures stratégie de détruire l'objet et qu'il est utile que si l'objet est utilisé dans le code non managé où le garbage collector ne pouvez pas garder une trace de l'utilisation. Cela ne veut pas dire que l'objet est dans la mémoire après la destruction.

Une fois qu'un objet commence la destruction du code de libérer des ressources (mémoire, gestionnaires de fichiers, les connexions réseau). L'ordre est habituellement d'au plus profond de la classe dérivée de retour à la classe de base. Si quelque chose dans le milieu étaient d'empêcher la destruction, il n'y a aucune garantie que ces ressources pourraient être acquis et de l'objet est dans un état incohérent.

Ce que vous voulez est plus probablement d'avoir un std::shared_ptr qui conserve la trace des copies et des références et seulement détruit l'objet une fois personne n'a besoin de elle plus.

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