Pourquoi un ptr faible ne peut-il pas être construit à partir d'un ptr unique?

Si je comprends bien, un weak_ptr n'augmente pas le nombre de référence de l'objet géré, donc il ne représente pas la propriété. Il vous permet simplement d'accéder à un objet dont la durée de vie est gérée par quelqu'un d'autre. Donc je ne vois pas vraiment pourquoi un weak_ptr ne peut pas être construit à partir d'un unique_ptr, mais seulement un shared_ptr.

quelqu'un Peut-il expliquer cette?

41
demandé sur Mat 2015-03-15 12:58:27
la source

7 ответов

std::weak_ptr ne peut pas être utilisé sauf si vous la convertissez std::shared_ptr au moyen de lock(). si le standard autorise ce que vous suggérez, cela signifie que vous devez convertir std:: weak_ptr en unique afin de l'utiliser, en violant l'unicité (ou en réinventant std::shared_ptr)

pour illustrer, considérons les deux morceaux de code:

std::shared_ptr<int> shared = std::make_shared<int>(10);
std::weak_ptr<int> weak(shared);

{
*(w.lock()) = 20; //OK, the temporary shared_ptr will be destroyed but the pointee-integer still has shared  to keep it alive
}

Maintenant, avec votre suggestion:

std::unique_ptr<int> unique = std::make_unique<int>(10);
std::weak_ptr<int> weak(unique);

{
*(weak.lock()) = 20; //not OK. the temporary unique_ptr will be destroyed but unique still points at it! 
}

ce Qui a été dit, vous pouvez suggérer qu'il existe une seule unique_ptr, et vous pouvez toujours déréférencement weak_ptr (sans créer d'autre unique_ptr), alors il n'y a pas de problème. Mais alors quelle est la différence entre unique_ptr et shared_ptr avec une référence? ou plus, quelle est la différence entre un unique_ptr et c-pointeurs un get en utilisant

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 le weak_ptr encore 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 un unique_ptr, il n'y a pas de compte de référence, donc il n'y a rien qui contient la référence compte, donc rien pour continuer à exister quand l'objet est parti. Donc il n'y a rien weak_ptr pour faire référence.

il n'y aurait pas non plus de façon saine d'utiliser un tel 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. C'est facile avec un shared_ptr -- c'est ce que l' shared_ptr ne. Mais comment voulez-vous faire avec un unique_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.

29
répondu David Schwartz 2015-03-15 13:24:37
la source

shared_ptr comporte essentiellement deux parties:

  1. le-pointu à l'objet
  2. le nombre de références d'objet

une fois que le nombre de référence tombe à zéro, l'objet (#1) est supprimé.

weak_ptr doit être en mesure de savoir si un objet existe toujours. Pour ce faire, il doit être capable de voir l'objet reference count (#2) s'il n'est pas zéro, il peut créer un shared_ptr pour l'objet (en incrémentant le nombre de références). Si le compte est à zéro il retournera un vide shared_ptr.

maintenant considérer quand l'objet reference count (#2) peut être supprimé? Nous devons attendre jusqu'à pas d' shared_ptr ou weak_ptr de l'objet de référence. À cette fin, l'objet de comptage de référence contient deux nombre de références, un fort ref et un faible réf. L'objet reference count ne sera supprimé que si les deux comptes sont nuls. Cela signifie qu'une partie de la mémoire peuvent être libérés après tout les références faibles ont disparu (ce qui implique un désavantage caché avec make_shared).

tl;dr;weak_ptr dépend d'un faible taux de référence qui fait partie de la shared_ptr, il ne peut pas y avoir un weak_ptr sans shared_ptr.

11
répondu Motti 2015-03-19 18:19:10
la source

du point de vue conceptuel, rien n'empêche une implémentation où un weak_ptr ne fournit qu'un accès et un unique_ptr contrôle 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 gérer les références faibles serait possible, mais nécessiterait une allocation dynamique supplémentaire. Depuis unique_ptr est censé éviter tout(!) gestion d'exécution sur un pointeur brut, que les frais généraux n'est pas acceptable.
  • afin d'utiliser l'objet référencé par un weak_ptr, vous devez extraire une référence" réelle " de celle-ci, qui validera d'abord que le pointeur n'est pas expiré en premier, puis vous donnera cette référence réelle (a shared_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. Cela ne peut pas être corrigé en retournant un pointeur mi-Fort mixte qui ne retarde que temporairement possible destruction du pointee, parce que vous pourriez tout aussi bien stocker celui-ci, aussi, défaire l'idée derrière unique_ptr.

je me demande juste, quel problème essayez-vous de résoudre en utilisant un weak_ptr ici?

8
répondu Ulrich Eckhardt 2015-03-15 13:24:33
la source

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 la correspondante shared_ptr s sont tous sortis de la portée et l'objet pointé a été désalloué et détruit. Cela signifie que shared_ptr S besoin de communiquer la destruction vers chacun weak_ptr vers le même objet d'une façon ou d'une autre. Cela a un certain coût – par exemple, une table de hachage globale doit être mise à jour, où weak_ptr récupère l'adresse de (ou nullptr si l'objet est détruit).

cela implique également le verrouillage dans un environnement multi-threadé, de sorte qu'il peut être trop lent pour certaines tâches.

cependant, le but de unique_ptr est de fournir un coût zéro classe d'abstraction de style RAII. Par conséquent, elle ne devrait pas entraîner d'autres coûts que ceux de deleteing (ou delete[] ing) l'objet affecté dynamiquement. Le délai imposé par un accès verrouillé ou autrement gardé à la table de hachage, pour exemple, peut être comparable au coût de la libération, cependant, qui n'est pas souhaitable dans le cas de unique_ptr.

5
répondu The Paramagnetic Croissant 2015-03-15 13:53:28
la source

on dirait que tout le monde écrit ici à propos de std::weak_ptr mais pas à propos de weak poiner concept qui je crois est ce que l'auteur demande

je pense que personne n'a mentionné pourquoi la bibliothèque standard ne fournit pas weak_ptr pour unique_ptr. Le concept de pointeur faible n'exclut pas l'utilisation de unique_ptr. Pointeur faible est seulement une information Si l'objet a déjà été supprimé donc ce n'est pas une magie mais très simple observateur généralisé modèle.

c'est à cause de threadsafety et consistency avec shared_ptr.

vous ne pouvez tout simplement pas garantir que votre weak_ptr (créé à partir de unique_ptr existant sur un autre thread) ne sera pas détruit pendant la méthode d'appel sur un objet pointé. C'est parce que weak_ptr doit être cohérent avec std::shared_ptr qui garantit threadsafety. Vous pouvez implémenter weak_ptr qui fonctionne correctement avec unique_ptr mais seulement sur la même méthode thread - lock inutile dans ce cas. Vous pouvez vérifier les sources de chrome pour base:: WeakPtr et base::WeakPtrFactory - vous pouvez l'utiliser librement avec unique_ptr. Le code de pointeur faible de chrome est très probablement basé sur la destruction du dernier membre - vous devez ajouter l'usine comme dernier membre et après cela je crois que WeakPtr est informé sur le deleteion d'objet (Je ne suis pas sûr à 100%) - donc il ne semble pas si difficile à mettre en œuvre.

globalement en utilisant unique_ptr avec le concept de pointeur faible est OK IMHO.

2
répondu Bartosz Piękny 2017-06-23 21:13:46
la source

Il peut être utile de distinguer les raisons de préférer un unique_ptr un shared_ptr.

Performances une raison évidente est le temps de calcul et l'utilisation de la mémoire. Selon la définition actuelle,shared_ptr les objets ont généralement besoin de quelque chose comme une valeur de référence-count, qui prend de l'espace et doit également être activement maintenu. unique_ptr objets ne le sont pas.

Sémantique Avec un unique_ptr, vous comme le programmeur avez une assez bonne idée quand le pointed-to object va être détruit: quand le unique_ptr est détruit ou lorsqu'une de ses méthodes modificatrices est appelée. Et ainsi de suite sur des bases de code larges ou peu familières, en utilisant unique_ptr transmet statiquement (et renforce) certaines informations sur le comportement d'exécution du programme qui pourraient ne pas être évidentes.

les commentaires ci-dessus ont généralement mis l'accent sur les raisons fondées sur le rendement pour lesquelles cela ne serait pas souhaitable pour weak_ptr objets d'être lié à l' unique_ptr objets. Mais on peut se demander si l'argument fondé sur la sémantique est une raison suffisante pour justifier une version future du LTS afin de soutenir le cas d'utilisation implicite de la question initiale.

0
répondu Christian Convey 2015-10-14 23:47:30
la source