28 votes

Meilleure pratique pour le retour des pointeurs intelligents

Quelle est la meilleure pratique pour retourner un pointeur intelligent, par exemple un boost::shared_ptr ? Dois-je retourner le pointeur intelligent ou le pointeur brut sous-jacent ? Je viens du C# et j'ai donc tendance à toujours retourner les pointeurs intelligents, parce que cela me semble correct. Comme ceci (en sautant la const-correctness pour un code plus court) :

class X
{
public:
    boost::shared_ptr<Y> getInternal() {return m_internal;}

private:
    boost::shared_ptr<Y> m_internal;
}

Cependant, j'ai vu certains codeurs expérimentés renvoyer le pointeur brut, et mettre les pointeurs bruts dans des vecteurs. Quelle est la bonne façon de procéder ?

21voto

Edouard A. Points 5047

Il n'y a pas de "bonne" manière. Cela dépend vraiment du contexte.

Vous pouvez gérer la mémoire en interne avec un pointeur intelligent et donner en externe des références ou des pointeurs bruts. Après tout, l'utilisateur de votre interface n'a pas besoin de savoir comment vous gérez la mémoire en interne. Dans un contexte synchrone, cette méthode est sûre et efficace. Dans un contexte asynchrone, les pièges sont nombreux.

Si vous n'êtes pas sûr de ce que vous devez faire, vous pouvez renvoyer les pointeurs intelligents à votre appelant. L'objet sera désalloué lorsque le nombre de références atteindra zéro. Assurez-vous simplement que vous n'avez pas une classe qui garde les pointeurs intelligents d'objets pour toujours, empêchant ainsi la désallocation lorsque cela est nécessaire.

Enfin, en C++, il ne faut pas abuser des objets alloués dynamiquement. Il y a de nombreux cas où vous n'avez pas besoin d'un pointeur et où vous pouvez travailler sur des références et des références constantes. C'est plus sûr et cela réduit la pression sur l'allocateur de mémoire.

11voto

Todd Gardner Points 8688

Cela dépend de la signification du pointeur.

En renvoyant un pointeur partagé, vous dites syntaxiquement "Vous partagerez la propriété de cet objet", de sorte que, si l'objet conteneur original meurt avant que vous ne libériez votre pointeur, cet objet existera toujours.

Renvoyer un pointeur brut signifie : "Vous connaissez cet objet, mais vous ne le possédez pas". C'est une façon de passer le contrôle, mais sans garder la durée de vie liée au propriétaire initial.

(dans certains anciens programmes c, cela signifie "C'est maintenant votre problème de me supprimer", mais je vous recommande fortement d'éviter celui-ci)

En général, le choix par défaut du partage m'évite bien des soucis, mais cela dépend de votre conception.

8voto

iain Points 4876

Je suis les directives suivantes pour passer des arguments de type pointeur aux fonctions et retourner des pointeurs :

boost::shared_ptr

L'API et le client partagent la propriété de cet objet. Cependant, vous devez faire attention à éviter les références circulaires avec les objets shared_ptr si les objets représentent une sorte de graphe. J'essaie de limiter mon utilisation de shared_ptr pour cette raison.

boost::weak_ptr / raw pointer

L'API possède cet objet, vous êtes autorisé à le partager tant qu'il est valide. S'il y a une chance que le client vive plus longtemps que l'API, j'utilise un weak_ptr.

std::auto_ptr

L'API crée un objet mais le client possède l'objet. Cela garantit que le code de retour est protégé contre les exceptions et indique clairement que la propriété est transférée.

boost::scoped_ptr

Pour les pointeurs vers des objets stockés sur la pile ou comme variables de membres de classe. J'essaie d'utiliser scoped_ptr d'abord.

Comme toutes les lignes directrices, il y aura des moments où les règles seront contradictoires ou devront être contournées, j'essaie alors de faire preuve d'intelligence.

5voto

Johann Gerell Points 10649

En général, je renvoie des pointeurs intelligents "propriétaires"/"uniques" à partir de fabriques ou autres afin de préciser qui est responsable du nettoyage.

Cet exemple https://ideone.com/qJnzva montre comment retourner un std::unique_ptr qui sera supprimée lorsque la portée de la variable à laquelle l'appelant attribue la valeur sortira de sa portée.

S'il est vrai que le pointeur intelligent supprime son propre pointeur, la durée de vie de la variable contenant le pointeur intelligent est contrôlée à 100 % par l'appelant, qui décide donc du moment où le pointeur est supprimé. Cependant, puisque c'est un pointeur intelligent "unique" et "propriétaire", aucun autre client ne peut contrôler la durée de vie.

4voto

TimW Points 5715

Je ne renverrais jamais un pointeur brut, mais plutôt un weak_ptr pour indiquer à l'utilisateur du pointeur qu'il n'a pas le contrôle de la ressource.

Si vous retournez un weak_ptr, il est très peu probable qu'il y ait des pointeurs dangling dans l'application.

S'il y a un problème de performance, je renverrais une référence à l'objet et une méthode hasValidXObject.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X