Question

Dans un projet C ++ qui utilise des pointeurs intelligents, tels que boost::shared_ptr, ce qui est une bonne philosophie de conception concernant l'utilisation de " this "?

Considérez que:

  • Il est dangereux de stocker le pointeur brut contenu dans un pointeur intelligent pour une utilisation ultérieure. Vous avez donné le contrôle de la suppression de l'objet et faites confiance au pointeur intelligent de le faire au bon moment.

  • Les membres de la classe non-statiques utilisent intrinsèquement un pointeur this . Il est un pointeur brut et qui ne peut être modifié.

Si je stocke jamais this dans une autre variable ou passer à une autre fonction qui pourrait stocker pour plus tard ou se lier dans un rappel, je crée des bugs qui sont introduits quand quelqu'un décide de faire un pointeur partagé à ma classe .

Étant donné que, quand est-il toujours approprié pour moi d'utiliser explicitement un pointeur this? Est- paradigmes de conception là-bas qui peuvent empêcher les bugs liés à cela?

Était-ce utile?

La solution

Alors que je n'ai pas de réponse générale ou d'un idiome, il est boost::enable_shared_from_this . Il vous permet d'obtenir un shared_ptr la gestion d'un objet qui est déjà géré par shared_ptr. Etant donné que dans une fonction de membre, vous avez aucune référence à ceux qui gèrent des années shared_ptr, enable_shared_ptr ne vous permet d'obtenir une instance de shared_ptr et passer que lorsque vous devez passer le pointeur this.

Mais cela ne résoudra pas le problème de passer this à partir du constructeur, car à ce moment-là, ne shared_ptr gère encore votre objet.

Autres conseils

Mauvaise question

  

Dans un projet C ++ qui utilise des pointeurs intelligents

La question n'a rien à voir avec des pointeurs intelligents en fait. Il est seulement sur la propriété.

pointeurs intelligents ne sont que des outils

Ils ne changent WRT le concept de propriété, esp. la nécessité d'avoir la propriété bien définis dans votre programme , le fait que la propriété peut être transféré volontairement, mais ne peut être prise par un client.

Vous devez comprendre que les pointeurs intelligents (aussi des serrures et d'autres objets RAII) représentent une valeur et une relation de WRT cette valeur en même temps. Un shared_ptr est une référence à un objet et établit une relation: l'objet ne doit pas être détruit avant cette shared_ptr, et quand cette shared_ptr est détruite, si elle est le dernier aliasing cet objet, l'objet doit être détruit immédiatement. (unique_ptr peut être considéré comme un cas particulier de shared_ptr où il y a aliasing zéro par définition, de sorte que le unique_ptr est toujours le dernier aliasing d'un objet.)

Pourquoi devriez-vous utiliser des pointeurs intelligents

Il est recommandé d'utiliser des pointeurs intelligents car ils expriment beaucoup avec uniquement des variables et des déclarations de fonctions.

pointeurs intelligents ne peuvent exprimer une prise conception bien définie, ils ne sont pas loin de la nécessité de définir la propriété. En revanche, la collecte des ordures enlève la nécessité de définir qui est responsable de la libération de la mémoire. (Mais ne prenez pas la nécessité, de définir qui est responsable d'autres ressources de nettoyage.)

Même dans les langues non-déchets collectés purement fonctionnel, vous devez faire la propriété claire: vous ne voulez pas écraser la valeur d'un objet si d'autres composants doivent encore l'ancienne valeur. Cela est notamment vrai en Java, où le concept de propriété de la structure de données mutable est extrêmement important dans les programmes filetés.

Qu'en est-il des pointeurs premières?

L'utilisation d'un pointeur brut ne signifie pas qu'il n'y a pas de propriété. Il est tout simplement pas décrit par une déclaration variable. Il peut être décrit dans les commentaires, dans vos documents de conception, etc.

Voilà pourquoi beaucoup de programmeurs C ++ considèrent que l'utilisation de pointeurs bruts au lieu du pointeur intelligent adéquat est inférieure : parce qu'il est moins expressif (je l'ai évité les termes « bon » et « mauvais » sur le but). Je crois que le noyau Linux serait plus lisible avec quelques objets C ++ pour exprimer les relations.

Vous pouvez mettre en œuvre une conception spécifique avec ou sans pointeurs intelligents. La mise en œuvre qui utilise le pointeur intelligent de façon appropriée être considérée comme supérieure par de nombreux programmeurs C ++.

Votre vraie question

  

Dans un projet C ++, ce qui est une bonne philosophie de conception concernant l'utilisation de « ce »?

C'est terriblement vague.

  

Il est dangereux de stocker le pointeur brut pour une utilisation ultérieure.

Pourquoi avez-vous besoin d'un pointeur pour une utilisation ultérieure?

  

Vous avez donné le contrôle de la suppression de l'objet et faites confiance à la composante responsable de le faire au bon moment.

En effet, une composante est responsable de la durée de vie de la variable. Vous ne pouvez pas prendre la responsabilité. Il doit être transféré

  

Si je stocke jamais cela dans une autre variable ou passer à une autre fonction qui pourrait stocker pour plus tard ou se lier dans un rappel, je crée des bugs qui sont introduits quand quelqu'un décide d'utiliser ma classe.

Il est évident que, puisque l'appelant n'est pas informé que la fonction cachera un pointeur et utiliser plus tard, sans le contrôle de l'appelant, vous créez des bugs.

La solution est évidemment soit:

  • responsabilité de transfert pour gérer la durée de vie de l'objet à la fonction
  • assurez-vous que le pointeur n'est enregistré et utilisé sous le contrôle de l'appelant

Seulement dans le fcas IRST, vous pourriez finir par un pointeur intelligent dans la mise en œuvre de la classe.

La source de votre problème

Je pense que votre problème est que vous essayez difficile de compliquer les choses en utilisant des pointeurs intelligents. pointeurs intelligents sont des outils pour faciliter les choses, pas plus dur. Si des pointeurs intelligents compliquez vos spécifications, puis repenser vos spécifications en terme des choses plus simples.

Ne pas essayer d'introduire des pointeurs intelligents comme une solution avant d'avoir un problème.

qu'introduire des pointeurs intelligents pour résoudre un problème précis et bien définis. Parce que vous ne décrivez pas un problème précis et bien définis, il est impossible de discuter d'une solution spécifique (impliquant des pointeurs intelligents ou non).

Un exemple d'utilisation correcte est return *this; dans des fonctions comme opérateur ++ () et l'opérateur << ().

Lorsque vous utilisez une classe de pointeur intelligent, vous avez raison est dangereux d'exposer directement « this ». Il y a des classes de pointeur liées à boost::shared_ptr<T> qui peuvent être utiles:

  • boost::enable_shared_from_this<T>
    • Fournit la possibilité d'avoir un objet retourne un pointeur partagé à lui-même qui utilise les mêmes données de comptage de référence en tant que pointeur partagé existant à l'objet
  • boost::weak_ptr<T>
    • travaille main dans la main avec des pointeurs partagés, mais ne tient pas une référence à l'objet. Si tous les pointeurs partagés disparaissent et l'objet est libéré, un pointeur faible sera en mesure de dire que l'objet n'existe plus et vous retourner NULL au lieu d'un pointeur vers la mémoire non valide. Vous pouvez utiliser des pointeurs faibles pour obtenir des pointeurs partagés à un objet de référence compté valide.

Aucun de ceux-ci est à toute épreuve, bien sûr, mais ils vont au moins rendre votre code plus stable et sûr, tout en offrant un accès approprié et le comptage de référence pour vos objets.

Si vous devez utiliser this, il suffit d'utiliser explicitement. pointeurs intelligents enveloppent seulement des pointeurs des objets qu'ils possèdent - soit exclusivelly (unique_ptr) ou de manière partagée (shared_ptr).

Je tiens personnellement à utiliser le ce pointeur lorsque vous accédez à des variables membres de la classe. Par exemple:

void foo::bar ()
{
    this->some_var += 7;
}

Il est juste une question inoffensive de style. Certaines personnes aiment, somepeople ne le font pas.

Mais en utilisant le ce pointeur pour toute autre chose est susceptible de causer des problèmes. Si vous avez vraiment besoin de faire des choses de fantaisie avec elle, vous devriez vraiment revoir votre conception. J'ai vu un code qui, dans le constructeur d'une classe, il a attribué le pointeur à un autre ce pointeur stocké quelque part ailleurs! C'est juste fou, et je ne peux pas penser jamais une raison de le faire. Le code entier était un énorme gâchis, par la manière.

Pouvez-vous nous dire ce que vous voulez exactement faire avec le pointeur?

Une autre option utilise des pointeurs intelligents intrusives, et en prenant soin de comptage de référence dans l'objet lui-même, et non pas les pointeurs. Cela nécessite un peu plus de travail, mais est en réalité plus efficace et facile à contrôler.

Une autre raison de passer autour est si vous voulez garder un registre central de tous les objets. Dans le constructeur, un objet appelle une méthode statique du registre à ce sujet. Il est utile pour divers publish / subscribe mécanismes, ou lorsque vous ne voulez pas que le registre à besoin de savoir ce que les objets / classes sont dans le système.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top