Comment attribuer une adresse à un objet existant à un pointeur intelligent?
#include <memory>
class bar{};
void foo(bar &object){
std::unique_ptr<bar> pointer = &object;
}
Je veux attribuer une adresse de l'objet à l'aide du pointeur. Le code ci-dessus évidemment l'habitude de compiler, parce que le côté droit de l'opérateur d'affectation doit être un std::unique_ptr. J'ai déjà essayé ceci:
pointer = std::make_unique<bar>(object)
Mais il génère de nombreuses erreurs lors de la compilation. Comment puis-je le faire?
Mise à jour
Comme dit dans les réponses à l'aide de la std::unique_ptr::reset
méthode conduit à un comportement indéterminé. Maintenant, je sais que, dans ce cas, je devrais utiliser un pointeur.
source d'informationauteur Tomasz Kasperczyk
Vous devez vous connecter pour publier un commentaire.
Essayer std::unique_ptr::reset
Mais attention, ce n'est pas recommandévous ne devez pas créer un
unique_ptr
à une référence qui est passé à une fonction. À la fin de la fonction, lorsquepointer
est en train d'être détruit, il va tenter de détruireobject
ainsi, et il ne sera disponible à l'extérieur de l'appel de la fonction, ce qui entraîne un accès à la mémoire d'erreur.Exemple: Cette compile, mais donnez-erreur à l'exécution.
D'autre part, vous pouvez envisager d'utiliser shared_ptr cela peut vous aider à vous décider: unique_ptr ou shared_ptr?.
Vous ne pouvez affecter qu'un autre
unique_ptr
ou lanullptr
. Si vous pensez à ce sujet, cela fait sens, trop (bien quereset
vous permettra de faire ce que vous voulez, mais je pense que c'est effectivement un bug ou d'une carence dansunique_ptr
).Un
unique_ptr
est le propriétaire exclusif de la pointe-de objet. Quand elle est hors de portée, il va supprimer l'objet.Cela signifie que votre fonction a évier sémantique. Le pointeur de vous passer (ou plutôt de la pointe-à l'objet") est consommée, qui est, il "disparaît" (puits) à l'intérieur de la fonction. Vous pouvez passer d'un objet par référence (un objet qui n'est même pas nécessairement allouées sur la pile, préparer une surprise si vous passez un objet avec stockage automatique!) et tout à coup il a disparu. Bang.
Évier de la sémantique doit être informé correctement. Vous devez passer une
unique_ptr
en tant que paramètre de la fonction. Unique pointeurs ne peuvent pas être copiés, ce qui permettra de forcer l'utilisateur de la fonction à utiliserstd::move
la création de de sensibilisation de ce qui est acutally passe.Avoir un objet "disparaître" est une mauvaise surprise, cela ne se produit pas seulement accidentellement.
On pourrait appeler
std::unique_ptr::reset
:mais la vraie question est: Est-ce vraiment ce que vous attendez d'elle? Si l'objet n'a pas été créé par
new
le ci-dessus peut être très dangereux. Étant donné que vous n'avez pas fourni de plus amples informations, vous pourrait valide de cas d'utilisation - mais sans cette information, il semble comme une source possible de futures difficultés. Ce que vous faites dans votre exemple, c'est que vous consommer l'objet, c'est à dire, une fois que la fonction a été appelée la durée de vie de launique_ptr
terminé et que l'objet a été supprimé. Si cela est documenté/clair à l'appelant, il pourrait être OK, sinon repenser la conception. Et même si c'est prévu à la conception, il est beaucoup mieux d'utiliser ununique_ptr
comme argument de la fonction elle-même:Cela ne signifie deux choses:
Permettez-moi de vous décevoir, mais vous n'avez pas. Vous avez là une référence, qui peut pointer vers un objet alloué dynamiquement ou une pile de objet alloué, ou, peut-être, d'un objet dans un tableau alloué dynamiquement, ce qui n'a pas été alloués individuellement.
Vous voulez placer son adresse dans une classe qui va automatiquement appeler delete sur cette adresse. Ce qui n'est pas valide pour la plupart des situations présentées ci-dessus. Ce qui est mauvais. Afin de passer une référence et de mettre l'adresse de la référence à un pointeur intelligent ne devrait jamais être fait, jamais. Surtout pas avec reset().
Au plus, ce que vous devez faire est d'initialiser le pointeur intelligent avec le nouvellement allouée objet, par exemple:
Ne jamais prendre l'adresse de référence. Jamais. Pour aucune raison. Il est moralement mauvais. Ce n'est pas parce que l'utilisation des adresses de référence n'est pas valide, car il peut être valable; c'est parce que deux mois plus tard, le nouveau collègue souhaitez utiliser cette adresse avec un pointeur intelligent parce que c'est comment (s)qu'il a entendu, c'est fait aujourd'hui, et puis venir à Débordement de Pile et de lire qu'ils devraient utiliser "reset" pour le pointeur. Ce qui est faux, douloureusement mal.
La fonction que vous recherchez est
reset()
. Voici un exemple:Ici
pointer
est ununique_ptr
. L'appel dereset()
va détruire l'objet précédent, géré parpointer
(s'il y a), et de faireobject
l'actuel objet géré depointer
.Ou, si vous voulez faire
object
l'objet géré droit lors de l'initialisation de launique_ptr
:Un mot d'avertissement cependant:
object
devraient être affectées avecnew
si vous allez gérer par ununique_ptr
parce queunique_ptr
peut essayer de les appelerdelete
sur elle. Si elle n'a pas été créé avecnew
n'est pas de l'envelopper dans ununique_ptr
ce n'est pas ce qu'ils sont pour.Ce que je peux voir, c'est, vous voulez avoir unique_ptr objet, qui pointe vers un objet de mémoire,mais vous ne voulez pas le transfert de la propriété de la mémoire.
Vous avez besoin pour créer des deleter pour l'objet, qui ne fait pas de supprimer l'objet:
unique_ptr est un modèle où le second argument est le deleter de l'objet. Par défaut, il est default_deleter, mais vous pouvez l'échanger avec ce faux:
post edit:
Même que vous pouvez faire avec shared_ptr, mais parce que shared_ptr peut être converti en d'autres shared_ptr à l'intérieur de l'arbre de l'héritage de l'objet, la deleter n'est pas stocké dans la catégorie modèle de l'argument, mais il est passé en tant que membre de l'instance. Cela rend plus facile à utiliser de l'OMI:
Vous pouvez faire quelques personnalisé de dégager des ressources ainsi: