Je vais essayer de pas te faire perdre ton boulot alors.
(Sauf que justement si je montre que ton design est sous-optimal, ça prouve mon point...)
Dès qu'il ne s'y intéresse plus? Ce n'est donc pas tout à fait un cache (ma première idée a été : mais c'est un cache!).
Donc quand la fonction cliente en a fini avec un T, elle détruit son shared_ptr<T>, le T est désalloué, mais il reste l'élément dans la map avec le weak_ptr<T> déconnecté ("null").
C'est voulu de garder cette trace de l'association en mémoire? Est-ce que cette association rompue comporte encore des informations utiles? Est-ce que cette entrée déconnectée va servir à optimiser la prochaine recherche du même objet, ou est-ce juste de la mémoire conservée inutilement?
(Tu me dis si je suis trop indiscret.)
Oui, c'est voulu. Ce qui est voulu, c'est qu'il reste une entrée dans la map portant le bon nom, que cette entrée est visible lors d'un parcours de la map, et que si l'utilisateur veut accéder à l'objet à nouveau, il le peut. Le déchargement dynamique est totalement transparent pour lui, il n'est même pas au courant qu'il existe.
Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.
Il a accès à quelquechose qui de son point de vue ressemble à une map<string, shared_ptr<T> >, mais en interne ressemble à une map<string, weak_ptr<T> > avec une instanciation automatique transparente à la demande.
Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.
Je comprends : x contient un shared_ptr vers y, y contient un shared_ptr vers x.
Autrement-dit x possède y, y possède x. Donc par transitivité x possède x! C'est absurde, quelque chose ne peut pas se posséder lui-même dans une gestion automatique des ressources.
Non, pas vraiment. Si une instance se possède elle-même, c'est en réalité qu'on fait de la gestion manuelle des ressources. Alors mieux vaut écrire "delete this;" que "me.reset();" (préférer ce qui est strait forward).
Dans le cadre d'une gestion automatique des ressources, basée sur des relations entre objets, relations matérialisées par des objets possédant (unique_ptr, shared_ptr, auto_ptr, etc.), relations correspondant au besoin effectif qu'a l'objet a d'avoir accès à l'objet b (a dépend de b, a possède b), l'auto-possession n'a aucun sens, elle est tautologique et triviale : tout objet a besoin de ses variables membre, introduire un objet possédant pour le matérialiser est absurde.
Je ne comprends toujours pas ce que les weak_ptr vont y faire.
Supposons : j'ai mon graphe de pointeurs, l'un pointant vers un autre, un cercle, quoi. Je fais quoi, concrètement, en C++?
Comment tu as fais? Pas en lisant la doc je pense?
Tu peux nous expliquer ce que fait enable_shared_from_this, et en quoi c'est une bonne solution à quel problème?
Avant de passer aux micro-optimisations, il faudrait préciser les contraintes imposées aux classes. (D'ailleurs, dans boost, enable_shared_from_this contient un weak_ptr qui contient deux pointeurs, donc c'est plus gros qu'un compteur de référence.)
La question est mal posée, évidemment. Ce qu'il faut que tu décides, c'est si toutes les instances de ta classe doivent être allouées dynamiquement, et être gérées par un système de smart pointer donné. (Il faut penser en terme de besoins et pas de composants standards.)
Toujours à propos de enable_shared_from_this, voici quelque chose de savoureux :
Et comment pourrait-il le faire? La classe de base enable_shared_from_this peut être inaccessible ou bien ambigüe (ou les deux). Par définition, il n'est pas possible de tester si une classe de base est inaccessible ou ambigüe.Envoyé par N2315, 20.6.6.4/14 [util.smartptr.enab]
C'est pour cela qu'il vaut mieux toujours dériver de manière public de enable_shared_from_this.
Justement, je ne vois pas. Voila exactement ce que je comprends :
Si on a graphe avec un cycle, et qu'on retire suffisamment d'arêtes, on peut obtenir un graphe sans cycle.
Comme ici on discute de C++, pas de théorie des graphes, et que le résultat ci-dessus est en plus assez trivial, je déduis que ce n'est pas ça que tu cherches à m'expliquer.
Quand tu me dis que weak_ptr suffit à résoudre le problème, tu pourrais aussi bien me dire qu'il suffit de voter pour le Parti de la Méditation Transcendantale (au fait, ils se présentent au municipales?) pour résoudre un problème de gestion de ressources en C++, ça me ferais le même effet : c'est possible qu'ils aient la solution au problème, mais je ne sais pas quelle est cette solution.
Le problème dont il est question ne peut pas être : comment éviter d'avoir "x contient un shared_ptr vers y, y contient un shared_ptr vers x". Pour ne pas avoir cette situation, il faut (et il suffit) de ne pas provoquer la situation où "x contient un shared_ptr vers y, y contient un shared_ptr vers x".
Chercher la solution de "x contient un shared_ptr vers y, y contient un shared_ptr vers x", c'est pour moi comme se demander si la phrase "La vache doit me touche de la jeudi" comporte une faute d'accord, où si tu préfère, comme poser la question : si x = 1/0, x \in R, quelle est valeur de x?
Il doit y avoir un problème de C++, qui doit être de la forme "comment faire quelque chose en C++", pas "pourquoi mon programme qui n'utilise pas weak_ptr ne marche pas?", ni "est-ce qu'un programme qui utilise weak_ptr peut ne pas avoir une caractéristique qu'a un programme "semblable" qui n'utilise pas weak_ptr?".
Si c'est requis quelque part, je ne l'ai pas vu. Si ça ne l'est pas, l'implémentation doit faire fonctionner :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5 class B; class A : enable_shared_from_this<B> {}; class B : A, enable_shared_from_this<B> {}; shared_ptr<B> p (new B);
Le weak_ptr, ce sont les arêtes que tu supprimes, mais dont tu as tout de même besoin.
Si tu dois parcourir le graphe pour supprimer à la main les éléments, il te faudra un garbage collector, donc ça ne marche pas.
Est-ce que tu as regardé les liens donnés sur la page des smart_ptr ? En particulier celui-ci http://boost.org/libs/smart_ptr/smart_ptr.htm ?
Tout en bas, les références, ils parlent des weak_ptr![]()
Ceci : "[E&D-94] John R. Ellis & David L. Detlefs, Safe, Efficient Garbage Collection for C++, Usenix Proceedings, February, 1994. This paper includes an extensive discussion of weak pointers and an extensive bibliography"?
Bon, ça ne va parler de boost::weak_ptr (weak_ptr.hpp : (c) 2001, 2002, 2003 Peter Dimov), mais ça peut être intéressant.
Par rapport à boost :
Assez ironique de la part de boost de citer ça.Envoyé par Safe, Efficient Garbage Collection for C++, 3.4. Smart pointers
Tout le contraire des "smart pointers", donc.Envoyé par Safe, Efficient Garbage Collection for C++, 2.2. Coexistence
C'est passablement obsolète, par endroit :
(Les templates membres ne devaient pas exister à l'époque?)Envoyé par Safe, Efficient Garbage Collection for C++, 3.4. Smart pointers
Il est me semble t-il évident, bien que je ne le lise explicitement nul part, qu'on parle d'un gc pur jus, qui gère les cycles de pointeurs.
D'ailleurs, en cherchant "cycle", la première occurrence est :
Donc à contrario, les cycles d'objets sans "clean-up functions" vont être collectés, c'est en tous cas ce que je comprends.Envoyé par Safe, Efficient Garbage Collection for C++, 5.1. Object clean-up
Donc le cas de pointeurs cycliques que tu décris est géré automatiquement par ce système, il n'y a aucun besoin d'utiliser des "weak pointers".
Partager