57 votes

Comment fonctionne faible_ptr?

Je comprends comment utiliser weak_ptr et shared_ptr . Je comprends comment fonctionne shared_ptr , en comptant le nombre de références dans son objet. Comment fonctionnent weak_ptr ? J'ai essayé de lire le code source boost, et je ne suis pas suffisamment familiarisé avec boost pour comprendre tout ce qu'il utilise.

Merci.

98voto

Paul Groke Points 2799

shared_ptr utilise supplémentaires "à l'encontre" de l'objet (aka. "partagé comte" ou "bloc de contrôle") pour stocker le nombre de références. (BTW: que de "contre" objet stocke également la deleter.)

Chaque shared_ptr et weak_ptr contient un pointeur vers le réel pointee, et un deuxième pointeur vers le "compteur" de l'objet.

Pour mettre en oeuvre weak_ptr, le "compteur" objet stocke deux compteurs différents:

  • "Utiliser le compteur" est le nombre d' shared_ptr instances pointant vers l'objet.
  • Le "faible" nombre d'est le nombre d' weak_ptr instances pointant vers l'objet, en plus d'un si "utiliser le compteur" est toujours > 0.

Le pointee est supprimé lorsque le "nombre d'utilisations" atteint zéro.

Le "compteur" helper objet est supprimé lorsque le "faible" nombre d'arriver à zéro (ce qui signifie "utiliser le compteur" doit aussi être égal à zéro, voir ci-dessus).

Lorsque vous essayez d'obtenir un shared_ptr d'un weak_ptr, la bibliothèque atomiquement vérifie l' "utiliser le compteur", et si c'est > 0 il incrémente. Si cela réussit, vous obtenez votre shared_ptr. Si "utiliser le compteur" était déjà nul, vous obtenez un vide shared_ptr exemple à la place.


EDIT: Maintenant, pourquoi en ajouter un à la faiblesse de compter au lieu de libérer juste le "compteur" de l'objet lors de ces deux points de chute à zéro? Bonne question.

L'autre solution serait de supprimer le "compteur" de l'objet lorsque le "nombre d'utilisations" et le "faible" nombre d'retomber à zéro. Voilà la première raison: la Vérification de deux (pointeur de taille moyenne) compteurs atomiquement n'est pas possible sur toutes les plateformes, et même là où il est, c'est plus compliqué que de vérifier juste un compteur.

Une autre raison est que le deleter doit rester valide jusqu'à la fin de l'exécution. Depuis la deleter est stocké dans le "contre" de l'objet, cela signifie que le "compteur" objet doit rester valide. Envisager ce qui pourrait arriver si il y en a un shared_ptr et un weak_ptr à un objet, et ils sont remis à zéro à la même époque dans les threads simultanés. Disons que l' shared_ptr vient en premier. Il diminue l' "utiliser le compteur" à zéro, et commence à exécuter la deleter. Maintenant l' weak_ptr diminue le "faible" nombre d'à zéro, et trouve le "utiliser le compteur" est nul. De sorte qu'il supprime le "compteur" de l'objet, et avec elle la deleter. Alors que la deleter est toujours en cours d'exécution.

Bien sûr, il y aura différentes façons de s'assurer que le "compteur" de l'objet reste en vie, mais je pense que l'augmentation de la "faiblesse de compter", l'un est un très élégant et intuitif. Le "faible" nombre d'deviendra la référence prise en compte pour les "contre" de l'objet. Et depuis shared_ptrs de la référence de l'objet compteur, trop, trop, ils ont pour incrémenter le "faible"nombre d'.

Probablement encore plus intuitive, la solution serait d'augmenter le "faible" nombre d', pour chaque shared_ptr, puisque chaque shared_ptr détiennent une référence pour les "contre" de l'objet.

L'ajout d'un pour tous, shared_ptr des cas est juste une optimisation (permet d'économiser atomique incrémenter/décrémenter lors de la copie/affectation d' shared_ptr des cas).

5voto

RedX Points 7449

Excellente explication de STL (Stephan T. Lavavej) de Microsoft (avec quelques informations sur l'implémentation de Microsoft).

http://channel9.msdn.com/Shows/Going+Deep/C9-Lectures-Stephan-T-Lavavej-Advanced-STL-1-of-n

-7voto

user3726672 Points 1

En gros, un "weak" ordinaire "T*" pointeur qui vous permet de RÉCUPÉRER une référence forte, c'est à dire "shared_ptr", plus tard dans le code.

Juste comme un vulgaire T*, le weak ne fait pas de comptage de références. À l'interne, à l'appui de comptage de références sur l'arbitraire d'un type T, la STL (ou toute autre bibliothèque de la mise en œuvre de ce type de logique) crée un objet wrapper nous allons l'appeler "point d'Ancrage". "Point d'ancrage" n'existe que pour mettre en œuvre le compteur de référence et d' "lorsque le comte est de zéro, l'appel de supprimer" comportement dont nous avons besoin.

Dans une référence forte, le shared_ptr met en œuvre sa copie, l'opérateur=, constructeur, destructeur, et d'autres renseignements pertinents sur les Api de mise à jour de "point d'Ancrage"'s de comptage de référence. C'est comment un shared_ptr garantit que votre "T" vies pour exactement aussi longtemps que quelqu'un l'utilise. Dans un "weak", ces mêmes Api il suffit de copier l'Ancrage réel ptr autour. Ils ne font PAS de mise à jour des comptes de référence.

C'est pourquoi le plus important Api de "weak" sont "périmés" et de la mal-nommée "lock". "Expiré" vous indique si l'objet sous-jacent est toujours là - c'est à dire "il A déjà supprimé lui-même, parce que toutes les références sont allés hors de portée?". "Lock" (si on peut) de convertir le weak à une référence forte shared_ptr, la restauration de comptage de références.

BTW, "lock" est un nom terrible pour que l'API. Vous n'êtes pas (seulement), invoquant un mutex, vous êtes en train de créer une référence forte à partir d'un faible, avec ce "point d'Ancrage" de l'agir. Le plus grand défaut dans les deux modèles est qu'ils ne mettent pas en œuvre l'opérateur->, de sorte à faire n'importe quoi avec votre objet, vous devrez récupérer le brut "T*". Ils l'ont fait principalement pour soutenir des choses comme "shared_ptr", parce que les types primitifs ne prennent pas en charge le "->" de l'opérateur.

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