2010-02-27 8 views
2

Dans le pointeur intelligent shared_ptr, le comptage des références est utilisé. Cependant, le comptage des références a un problème, celui-ci ne peut pas casser les cycles de référence.Comptage des références avec cycles dans le pointeur intelligent C++

J'ai quatre questions à ce sujet.

1) Quelqu'un pourrait-il m'offrir un extrait dans lequel se sont produits les cycles de référence?

2) S'il ne peut pas rompre les cycles de référence, comment RCSP garantit-il la gestion des ressources de la réussite? Est-il possible de rompre les cycles avec un produit tiers?

3) Y a-t-il moyen d'éviter les cycles de référence?

4) Que diriez-vous d'autres pointeurs intelligents? Comment font-ils face à la source gérer? Par exemple, share_ptr, scope_ptr?

Merci beaucoup!

Répondre

9

La manière habituelle d'éviter les cycles est d'utiliser des références faibles dans n'importe quel point du cycle. shared_ptr a un type de compagnon, weak_ptr, qui est conçu à cet effet.

Quelle partie du cycle affaiblir est une question de conception. Dans les conceptions où les objets «parents» possèdent des «enfants», la référence du parent à l'enfant doit être forte (shared_ptr) et la référence de l'enfant au parent doit être faible (weak_ptr).

5

Les utilisations pratiques impliquant des cycles sont assez peu de types de graphiques. Un extrait trivial (si celui qui est peu susceptible de se produire dans la vie réelle) serait quelque chose comme:

struct node { 
    node *next; 
}; 

int create_cycle() { 
    node *a = new node; 
    a.next = a; 
} 

Après les retours de create_cycle, le nœud nous vient d'allouer contient une référence à lui-même, mais il n'y a aucun autre point à, donc un compteur de référence ne le récupèrera pas, même s'il est corrompu. Chris Jester-Young a déjà traité de la rupture de cycle avec des pointeurs intelligents d'un point de vue pratique.

Il n'est pas entré dans les détails sur la façon dont cela fonctionne en interne. Un weak_ptr est en quelque sorte un pointeur doublement indirect.

C'est à dire. le weak_ptr ne donne pas accès directement à un objet. Au lieu de cela, pour accéder à l'objet, vous devez convertir weak_ptr en shared_ptr, puis l'utiliser pour accéder à l'objet - mais la tentative de conversion de weak_ptr en shared_ptr ne réussira que s'il y a encore au moins un autre shared_ptr à l'objet géré (donc l'objet a un nombre de références différent de zéro et existe toujours). En tant que tel, weak_ptr vous donne accès à un objet aussi longtemps qu'il existe, mais "sait" quand l'objet cesse d'exister et ne vous donne pas accès à la mémoire (maintenant libérée) où l'objet utilisé pour être si l'objet a été détruit. Éviter les cycles dépend du type de tâches que vous utilisez. Si vous traitez beaucoup de graphiques (par exemple), ils sont souvent presque impossibles à éviter, simplement parce que certaines choses que vous modélisez ont des cycles. Sinon, eh bien ... ça dépend. Je suppose qu'un bon nombre de développeurs sont partis pour des carrières entières sans jamais avoir à créer une structure liée contenant un cycle. D'autres le font probablement plusieurs fois dans une semaine moyenne.

En ce qui concerne les autres pointeurs intelligents, comme indiqué ci-dessus, le type weak_ptr fonctionne en conjonction avec shared_ptr; vous pouvez utiliser shared_ptr sans jamais utiliser weak_ptr, mais pour utiliser vraiment un weak_ptr à un moment donné, vous devez le convertir en shared_ptr.

Questions connexes