| Xavier_OM |
masklinn a écrit :
Mais prominent, facile à utiliser, central au langage et qui ressemble à quelque chose.
|
:sarcastic:
el muchacho a écrit :
Facile à utiliser, c'est vite dit. Le problème avec les pointeurs qui se baladent, c'est le cycle de vie des objets sous-jacents. Tant qu'on reste dans un scope et qu'on fait du RAII, c'est facile, l'objet est créé au début du scope, et détruit en sortie. Dès qu'il sort du scope, il faut réfléchir à quand, comment et par qui il va être détruit. Quelques fois, c'est pas évident, parce qu'il faut en principe faire l'exhaustivité des cas possibles. Si on en oublie un, on a soit un pointeur nul, soit un memleak. A part à l'aide d'un garbage collector, qui sert justement à ça, je ne vois pas trop comment le langage permet de s'économiser cette réflexion.
|
En C++ tu as quelques trucs pour gérer correctement ta mémoire sans garbage collection :
La durée de vie de gadget est celle de ton instance widget :
Code :
- class Widget {
- private:
- Gadget g;
- };
|
La durée de vie de gadget est celle de ton instance de widget, mais tu partages ton gadget entre différents objets. Tu peux utiliser un shared pointer pour avoir un comptage de référence automatique : la libération se fera automatiquement quand le compteur sera à 0, quand mourra le dernier objet qui possédait une référence vers ce gadget :
Code :
- class Widget
- private:
- shared_ptr<Gadget> g;
- }
|
Presque comme shared_ptr, tu partages une référence entre plusieurs classes, sauf que les weak_ptr ne comptent pas dans le comptage de référence automatique mais peuvent tester si la libération a déjà été faite. Pas mal pour éviter les cycles si tu veux vraiment qu'un objet A possède B et que B possède A.
Code :
- class Gadget {
- private:
- weak_ptr<Widget> parent;
- }
|
Exemple :
Code :
- shared_ptr<Widget> w = parent.lock(); // toujours là ?
- if (w) {
- // on ne passe jamais ici si parent a été nettoyé, cad quand plus personne ne détient un shared_ptr vers parent.
- }
|
Tout ça type_safe et sans avoir à faire des trucs à la main du genre foutre soi-même NULL dans un Widget* ou stocker des flags 'disposable' pour savoir si oui ou non l'instance existe toujours.
À noter une petite variante très C++ : unique_ptr. C'est un peu comme un shared_ptr mais quand tu sais qu'un et un seul truc sera responsable de ton objet. Si node est le seul à posséder ses enfants, et qu'il ne partage ça avec personne, tu peux utiliser unique_ptr et c'est un peu mieux niveau perf qu'un shared_ptr partagé par une seule instance.
Code :
- class Node {
- private:
- vector< unique_ptr<Node> > children;
- }
|
Mais globalement c'est pas très différent.
Bref si tu construits proprement ton truc, tu ne risques pas trop de te demander "est-ce que je dois faire delete ou est-ce que c'est quelqu'un d'autre qui s'en charge ?". Au final tu écris très peu de delete d'ailleurs [:spamafote] Ton vrai problème commence quand tu tombes sur du C++ pensé comme du C (et c'est pas si rare) blindé de new/delete "kivonbien" je trouve :o |