Je souhaite transmettre un pointeur partagé à une fonction. Pouvez-vous m'aider?
Bien sûr, je peux vous aider. Je suppose que vous avez une certaine compréhension de la sémantique de propriété en C ++. Est-ce vrai?
Ouais, je suis assez à l'aise avec le sujet.
Bien.
Ok, je ne peux penser qu'à deux raisons de prendre un shared_ptr
argument:
- La fonction veut partager la propriété de l'objet;
- La fonction effectue une opération qui fonctionne spécifiquement sur
shared_ptr
s.
Laquelle vous intéresse?
Je cherche une réponse générale, donc je m'intéresse aux deux. Je suis curieux de savoir ce que vous voulez dire dans le cas n ° 2, cependant.
Des exemples de telles fonctions incluent std::static_pointer_cast
des comparateurs personnalisés ou des prédicats. Par exemple, si vous avez besoin de trouver tous les shared_ptr uniques à partir d'un vecteur, vous avez besoin d'un tel prédicat.
Ah, quand la fonction a réellement besoin de manipuler le pointeur intelligent lui-même.
Exactement.
Dans ce cas, je pense que nous devrions passer par référence.
Oui. Et si cela ne change pas le pointeur, vous voulez passer par référence const. Il n'est pas nécessaire de copier puisque vous n'avez pas besoin de partager la propriété. C'est l'autre scénario.
Ok, compris. Parlons de l'autre scénario.
Celui dont vous partagez la propriété? D'accord. Avec quoi partagez-vous la propriété shared_ptr
?
En le copiant.
Ensuite, la fonction devra faire une copie d'un shared_ptr
, correct?
Évidemment. Alors je le passe par une référence à const et je le copie dans une variable locale?
Non, c'est une pessimisation. S'il est passé par référence, la fonction n'aura d'autre choix que de faire la copie manuellement. S'il est passé par valeur, le compilateur choisira le meilleur choix entre une copie et un déplacement et l'exécutera automatiquement. Alors, passez par valeur.
Bon point. Je dois me rappeler plus souvent cet article " Vous voulez de la vitesse? Passez par la valeur. "
Attendez, que se passe-t-il si la fonction stocke le shared_ptr
dans une variable membre, par exemple? Cela ne fera-t-il pas une copie redondante?
La fonction peut simplement déplacer l' shared_ptr
argument dans son stockage. Déplacer un shared_ptr
est bon marché car cela ne change aucun nombre de références.
Ah, bonne idée.
Mais je pense à un troisième scénario: et si vous ne voulez pas manipuler le shared_ptr
, ni partager la propriété?
Dans ce cas, cela shared_ptr
n'a aucun rapport avec la fonction. Si vous souhaitez manipuler la pointee, prenez une pointee et laissez les appelants choisir la sémantique de propriété qu'ils souhaitent.
Et dois-je prendre la pointee par référence ou par valeur?
Les règles habituelles s'appliquent. Les pointeurs intelligents ne changent rien.
Passez par valeur si je vais copier, passez par référence si je veux éviter une copie.
Droite.
Hmm. Je pense que vous avez oublié un autre scénario. Et si je veux partager la propriété, mais uniquement en fonction d'une certaine condition?
Ah, un cas de pointe intéressant. Je ne m'attends pas à ce que cela arrive souvent. Mais quand cela se produit, vous pouvez soit passer par valeur et ignorer la copie si vous n'en avez pas besoin, soit passer par référence et faire la copie si vous en avez besoin.
Je risque une copie redondante dans la première option et perd un mouvement potentiel dans la seconde. Je ne peux pas manger le gâteau et l'avoir aussi?
Si vous êtes dans une situation où cela compte vraiment, vous pouvez fournir deux surcharges, l'une prenant une référence const lvalue et l'autre prenant une référence rvalue. L'un copie, l'autre bouge. Un modèle de fonction de transfert parfait est une autre option.
Je pense que cela couvre tous les scénarios possibles. Merci beaucoup.
const std::shared_ptr<myClass>& arg1