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_ptr
s 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).