Comment passer le pointeur const à l'objet const en utilisant unique_ptr
Je veux passer un unique_ptr
à une fonction d'assistance, et je veux faire en sorte que la fonction d'assistance ne modifie le pointeur, ni de l'objet pointé. Sans le unique_ptr
la solution est d'avoir
void takePtr(AClass const * const aPtr) {
//Do something with *aPtr.
//We cannot change aPtr, not *aPtr.
}
(Enfin, techniquement, AClass const * aPtr
est suffisant.) Et je peux appeler cela avec
AClass * aPtr2 = new AClass(3);
takePtr(aPtr2);
Je veux utiliser à la place unique_ptr
mais ne peut pas comprendre comment écrire ceci. J'ai essayé
void takeUniquePtr(unique_ptr<AClass const> const & aPtr) {
//Access *aPtr, but should not be able to change aPtr, or *aPtr.
}
Quand je l'appelle avec
unique_ptr<AClass> aPtr(new AClass(3));
takeUniquePtr(aPtr);
il ne compile pas. L'erreur que je vois est
testcpp/hello_world.cpp:141:21: error: invalid user-defined conversion from ‘std::unique_ptr<AClass>’ to ‘const std::unique_ptr<const AClass>&’ [-fpermissive]
Ne devrait pas la conversion de unique_ptr<AClass>
à unique_ptr<AClass const>
être automatique? Ce qui me manque ici?
Par la façon dont, si je change unique_ptr<AClass const> const & aPtr
à unique_ptr<AClass> const & aPtr
dans la définition de la fonction, il compile, mais je peux appeler des fonctions comme aPtr->changeAClass()
je ne veux pas permettre.
source d'informationauteur Yogeshwer Sharma
Vous devez vous connecter pour publier un commentaire.
Pointeurs intelligents sont pour la gestion de la propriété et la durée de vie, ils nous permettent (entre autres choses) à transférer en toute sécurité autour de la propriété les différentes parties de notre code.
Lorsque vous passez une
const unique_ptr<T>&
à une fonction (pas pertinent de savoir siT
estconst
ou pas), ce que cela signifie réellement, c'est que la fonction promet de ne jamais modifier launique_ptr
lui-même (mais il pourrait encore modifier le pointu de l'objet, siT
n'est pasconst
) ie. il n'y aura pas de possibilité de transfert de propriété que ce soit. Vous êtes juste en utilisant leunique_ptr
comme un inutile wrapper autour d'un pointeur nu.Donc, comme @MarshallClow suggéré dans un commentaire, vous devez simplement se débarrasser de l'emballage et de transmettre un nu pointeur ou une référence directe. Ce qui est cool c'est que votre code est maintenant sémantiquement clair (votre fonction de signature indique clairement qu'il ne plaisante pas avec la propriété, qui était pas immédiatement évident avec un
const unique_ptr<...>&
) et il permet de résoudre votre "constification" problème en même temps!À savoir:
Edit: pour répondre à votre question secondaire "pourquoi ne pas le compilateur laissez-moi ... fonte
unique_ptr<A>
àunique_ptr<A const>
?".En fait, vous pouvez déplacer un
unique_ptr<A>
à ununique_ptr<A const>
:Mais comme vous pouvez le voir, cela signifie un transfert de propriété de
p
àq
.Le problème avec ton code, c'est que vous êtes en passant un (référence)
unique_ptr<const A>
à une fonction. Car il y a un type de divergence avecunique_ptr<A>
pour le faire fonctionner, le compilateur doit instancier un temporaire. Mais, à moins que le transfert de propriété manuellement à l'aide destd::move
le compilateur va essayer de copie votreunique_ptr
et il ne peut pas le faire depuisunique_ptr
explicitement interdit.Remarquez comment le problème disparaît si vous déplacez le
unique_ptr
:Le compilateur est maintenant en mesure de construire une temporaire
unique_ptr<const A>
et déplacer l'originalunique_ptr<A>
sans casser vos attentes (puisqu'il est désormais clair que vous souhaitez déplacer, pas de copie).Donc, la racine du problème, c'est que
unique_ptr
a seulement la sémantique de déplacement, pas de copie de la sémantique, mais vous auriez besoin de la copie de la sémantique pour créer un temporaire et encore conserver la propriété par la suite. De l'oeuf et de poulet,unique_ptr
n'est tout simplement pas conçu de cette façon.Si vous considérez maintenant
shared_ptr
qui a la sémantique de copie, le problème disparaît aussi.La raison en est que le compilateur est maintenant en mesure de créer un temporaire
std::shared_ptr<const int>
copie (automatiquement la conversion destd::shared_ptr<int>
) et lier temporaire à unconst
de référence.Je suppose que cela est plus ou moins le couvre, même si mon explication manque de standardese lingo et est peut-être pas aussi claire qu'elle devrait être. 🙂
Arrivés à cette vieille question sur const pointeurs intelligents.
Réponses ci-dessus, ignorer le simple modèle de solution.
Le template très simple option (option a)
cette solution permet toutes les options possibles de unique_ptr être envoyé à toto:
const unique_ptr<const int>
unique_ptr<const int>
const unique_ptr<int>
unique_ptr<int>
Si vous souhaitez éviter pour une raison 3 et 4 ci-dessus, ajouter const T:
Accepter seulement const/non-const unique_ptr à const! (option b)
Note de côté 1
Vous risquez de surcharger "option" et "option b" si pour obtenir un comportement différent pour les cas où vous pouvez ou ne pouvez pas modifier la valeur indiquée.
Note de côté 2
Si vous ne voulez pas de faire des changements à la valeur indiquée dans cette fonction (jamais!!!! quel que soit le type de paramètre que nous!) -- ne pas surcharger.
Avec "option b", le compilateur ne permet pas de changer la valeur que nous point de. Travail!
Si vous voulez soutenir tous les 4 cas, c'est à dire "option", la fonction peut encore "accidentellement" changement de la valeur que nous point de, par exemple,
cependant cela ne devrait pas être un problème si au moins une personne a T qui est en fait const, le compilateur n'aime pas dans ce cas et vous aider à trouver le problème.
Vous pouvez ajouter un appelant à l'unité-test, quelque chose comme:
Extrait de Code: http://coliru.stacked-crooked.com/a/a36795cdf305d4c7