Pourquoi pas un weak être construit à partir d'un unique_ptr?
Si je comprends bien, un weak_ptr
ne pas incrémenter le compteur de référence de l'objet géré, par conséquent, il ne représente pas la propriété. Il vous permet tout simplement d'accéder à un objet, la durée de vie qui est géré par quelqu'un d'autre.
Donc, je ne vois vraiment pas pourquoi une weak_ptr
ne peut pas être construit à partir d'un unique_ptr
, mais seulement un shared_ptr
.
Quelqu'un peut-il expliquer cette?
- Vous pourriez être intéressé par Une Proposition pour le Monde de la Plus bête des Smart Pointeur
- Cela a aussi à voir avec de possibles conséquences de performance (voir ma réponse ci-dessous).
- euh... ai-je bien compris que
observer_ptr
ne l'est pas... faire quelque chose? est-il tout simplement de sucre syntaxique pour ceux qui n'aiment pas les non-possesseurs d'un raw pointeurs? - Yup!
- heh, j'ai proposé la même chose à Herb Sutter en 2012, mais il haussa les épaules arrêt (en fait je l'ai écrit deux fois premier, ici).
Vous devez vous connecter pour publier un commentaire.
std::weak_ptr
ne peut pas être utilisé, sauf si vous le convertir enstd::shared_ptr
par les moyens delock()
. si le standard a permis ce que vous suggérez, ce qui signifie que vous avez besoin de convertir std::weak pour unique afin de l'utiliser, en violation de l'unicité (ou ré-inventerstd::shared_ptr
)Pour illustrer, considérons les deux morceaux de code:
Maintenant avec votre suggestion:
Qui a été dit, vous pouvez suggérer qu'il existe une seule
unique_ptr
, et vous ne pouvez toujours déréférencement deweak_ptr
(sans créer d'autreunique_ptr
), alors il n'y a pas de problème. Mais alors quelle est la différence entreunique_ptr
etshared_ptr
avec une référence? ou d'ailleurs, quelle est la différence entre un régulierunique_ptr
et C-pointeurs une utilisationget
?weak_ptr
n'est pas pour "général nonowning ressources", il a une très particulier - Le but principal deweak_ptr
est de prévenir la circulaire de pointage deshared_ptr
qui fera une fuite de mémoire. Autre chose qui doit être fait avec la plaineunique_ptr
etshared_ptr
.*w(1.lock()) = 20;
. J'imagine que devrait êtres1
?Si vous pensez à ce sujet, un
weak_ptr
doit se référer à quelque chose d'autre que l'objet lui-même. C'est parce que l'objet peut cesser d'exister (quand il n'y a plus forte pointeurs) et leweak_ptr
a encore de se référer à quelque chose qui contient les informations que l'objet n'existe plus.Avec un
shared_ptr
, que quelque chose est la chose qui contient le nombre de références. Mais avec ununique_ptr
, il n'y a pas de comptage de référence, donc il n'y a pas de chose qui contient le nombre de références, donc rien de continuer à exister lorsque l'objet a disparu. Donc, il n'y a rien pour unweak_ptr
de référence.Il y aurait également aucune façon saine de l'utilisation d'une telle
weak_ptr
. Pour l'utiliser, vous devez avoir une certaine façon de garantir que l'objet n'a pas été détruit lors de l'utilisation de ce. C'est facile avec unshared_ptr
-- c'est ce queshared_ptr
n'. Mais comment voulez-vous faire avec ununique_ptr
? Manifestement, vous ne pouvez pas avoir les deux, et quelque chose d'autre doit déjà l'objet ou il aurait été détruit depuis votre pointeur est faible.Un
shared_ptr
a en fait deux parties:Une fois la référence compteur tombe à zéro de l'objet (#1) est supprimé.
Maintenant un
weak_ptr
doit être en mesure de savoir si un objet existe toujours. Pour ce faire, il doit être en mesure de voir le nombre de références d'objet (#2) si ce n'est pas de zéro, on peut créer unshared_ptr
de l'objet (en incrémentant le nombre de références). Si le compteur est à zéro, il sera de retour un videshared_ptr
.Maintenant prendre en compte lorsque le compteur de référence de l'objet (#2) peuvent être supprimés? Nous devons attendre jusqu'à ce sans
shared_ptr
OUweak_ptr
objet de référence. À cette fin, le compteur de référence de l'objet tient deux comptes de référence, un forte ref et un faible réf. Le compteur de référence de l'objet ne seront supprimés lors de ses deux comptes sont à zéro. Cela signifie qu'une partie de la mémoire peuvent être libérés après toutes les références faibles ont disparu (ce qui implique une caché inconvénient avecmake_shared
).tl;dr;
weak_ptr
dépend d'un faible nombre de références qui fait partie deshared_ptr
, il ne peut pas être unweak_ptr
sansshared_ptr
.weak_ptr
est unshared_ptr
pour le compte de référence de l'objet.Sur le plan conceptuel, il n'y a rien qui empêche une mise en œuvre lorsqu'un weak donne uniquement accès et un unique_ptr des contrôles de la durée de vie. Cependant, il y a des problèmes:
unique_ptr
n'utilise pas de comptage de référence pour commencer. L'ajout de la structure de gestion pour la gestion de la faiblesse de références serait possible, mais nécessite un supplément de l'allocation dynamique. Depuisunique_ptr
est censé éviter tout(!) gestion d'exécution sur un pointeur brut, que les frais généraux n'est pas acceptable.weak_ptr
, vous avez besoin d'extraire une "vraie" référence à partir d'elle, qui va d'abord vérifier que le pointeur n'est pas expiré en premier et ensuite vous donner cette véritable référence (unshared_ptr
dans ce cas). Cela signifie que vous avez soudainement une deuxième référence à un objet qui est censé être uniquement possédé, ce qui est une recette pour les erreurs. Ce ne peut pas être fixé par le retour d'un mélange moitié-fort pointeur seulement temporairement délais de destruction de la pointee, parce que vous pourriez tout aussi bien en magasin qu'un, aussi, de vaincre l'idée derrièreunique_ptr
.Me demandais, quel problème essayez-vous de résoudre à l'aide d'un
weak_ptr
ici?Personne n'a mentionné l'aspect performance du problème, alors permettez-moi de jeter mon 0.02$.
weak_ptr
doit en quelque sorte de savoir quand le correspondantshared_ptr
s ont tous disparu de la portée et de l'objet pointé a été libéré et détruit. Cela signifie queshared_ptr
s doivent communiquer à la destruction à l'égard de chaqueweak_ptr
pour le même objet, en quelque sorte. Cela a un certain coût – par exemple, un mondial de la table de hachage doit être mis à jour, oùweak_ptr
obtient l'adresse du (ounullptr
si l'objet est détruit).Cela implique aussi de verrouillage dans un environnement multi-thread, donc il peut éventuellement être trop lent pour certaines tâches.
Cependant, l'objectif de
unique_ptr
est de fournir un à coût zéro RAII-style abstraction de la classe. Par conséquent, il ne devrait pas encourir de tout autre coût que celui dedelete
ing (oudelete[]
ing) de l'objet alloué dynamiquement. Le délai imposé par faire un blocage ou autrement gardé table de hachage d'accès, par exemple, peut être comparable au coût de la libération, cependant, qui n'est pas souhaitable dans le cas deunique_ptr
.Ressemble à tout le monde qui est écrit ici à propos de std::weak, mais pas par la faiblesse de la poiner concept qui, je crois, est ce que l'auteur demande
Je pense que personne n'a indiqué pourquoi la bibliothèque standard n'est pas de fournir weak pour unique_ptr. Faible pointeur CONCEPT n'est pas dénie unique_ptr d'utilisation. La faiblesse de pointeur n'est qu'une information si l'objet a déjà été supprimé de sorte qu'il n'est pas de la magie, mais très simple généralisée modèle observateur.
C'est à cause de threadsafety et de cohérence avec les shared_ptr.
Vous simplement ne pouvez pas garantir que votre weak (créé à partir de unique_ptr existant sur d'autres thread) sera pas détruit lors de l'appel de méthode sur un objet pointu.
C'est parce que weak doit être cohérente avec std::shared_ptr qui garantissent threadsafety. Vous pouvez mettre en œuvre weak qui fonctionne correctement avec unique_ptr, mais seulement sur le même thread - méthode de verrouillage n'est pas nécessaire dans ce cas. Vous pouvez le vérifier chrome sources de base: WeakPtr et la base::WeakPtrFactory - vous pouvez l'utiliser librement avec unique_ptr.
Chrome faible pointeur de code est très probablement basée sur le dernier membre de la destruction - vous besoin d'ajouter de l'usine en tant que dernier membre et après que je crois que WeakPtr est informé buter objet deleteion (je ne suis pas sûr à 100%) - de sorte qu'il n'a pas l'air si difficile à mettre en œuvre.
Globale à l'aide de unique_ptr avec de faibles pointeur concept est OK à mon humble avis.
Il peut être utile de distinguer les raisons de préférer un
unique_ptr
sur uneshared_ptr
.Performance Une raison évidente de calcul en temps et de mémoire. Tel qu'il est actuellement défini,
shared_ptr
les objets généralement besoin de quelque chose comme une référence-valeur de nombre, qui prend de l'espace et doivent également être activement maintenu.unique_ptr
objets ne le sont pas.Sémantique Avec un
unique_ptr
, vous en tant que programmeur avoir une assez bonne idée de la pointe-de objet est sur le point d'être détruites lorsque leunique_ptr
sont détruits, ou lorsque l'un de ses méthodes de modification est appelée. Et donc, sur grand ou inconnu des bases de code, à l'aide deunique_ptr
statiquement véhicule (et impose) quelques informations sur le programme d'exécution du comportement qui pourrait ne pas être évident.Les commentaires ci-dessus ont généralement mis l'accent sur la performance basée sur des raisons qu'il serait souhaitable pour
weak_ptr
objets liés àunique_ptr
objets. Mais on peut se demander si la sémantique basée sur l'argument est une raison suffisante pour une version future de la STL à l'appui le cas d'utilisation implicite de la question d'origine.