Avec l'avènement de std::unique_ptr
, Le défaut std::auto_ptr
Peut enfin être mis au repos. Donc depuis plusieurs jours, j'ai changé mon code pour utiliser des pointeurs intelligents et pour éliminer tout delete
de mon code.
Bien que valgrind affirme que mon code est propre en mémoire, la richesse sémantique des pointeurs intelligents rendra le code plus propre et plus facile à comprendre.
Dans la plupart du code, la traduction est simple: utilisez std::unique_ptr
Pour remplacer les pointeurs bruts détenus par les objets propriétaires, jetez delete
et saupoudrez soigneusement get()
, reset()
et move()
appelle, selon les besoins, pour bien s'interfacer avec le reste du code.
Je suis au point où je traduis pointeurs bruts non propriétaires en pointeurs intelligents maintenant.
Étant donné que je faisais attention à la durée de vie de mes objets (je m'assure que mes modules ne dépendent que dans une seule direction), valgrind me dit que je n'ai pas de lectures non initialisées, de pointeurs pendants ou de fuites. Donc, techniquement, je pourrais simplement laisser ces pointeurs bruts non propriétaires seuls maintenant.
Cependant, une option est de changer ces pointeurs bruts non propriétaires en std::shared_ptr
Parce que je sais qu'ils sont acycliques. Ou serait-il préférable de les laisser comme pointeurs bruts?
J'ai besoin de conseils de vétérans utilisateurs de pointeurs intelligents sur les règles générales que vous utilisez pour décider si vous souhaitez conserver pointeurs bruts non propriétaires tels quels ou pour traduisez-les en std::shared_ptr
, en gardant à l'esprit que je teste en continu et valde mon code en permanence.
EDIT: Je peux mal comprendre l'utilisation de std::shared_ptr
- peuvent-ils être utilisés en conjonction avec std::unique_ptr
, Ou est-il vrai que si j'utilise std::shared_ptr
, Toutes les poignées doivent également être std::shared_ptr
?
Personnellement, c'est ainsi que je le fais (plus ou moins):
J'utilise de loin plus d'unique_ptrs que de shared_ptrs, et plus de pointeurs bruts que de pointeurs faibles.
Utiliser un shared_ptr
lorsque vous avez besoin que plusieurs choses possèdent une ressource (et que ces choses peuvent entrer et sortir de la portée "au hasard"), utilisez un unique_ptr
lorsqu'une seule chose est propriétaire de la ressource, et utilisez un pointeur brut lorsque vous avez juste besoin de vous y référer sans en être le propriétaire (et attendez-vous à ce que cette référence ne dure pas plus longtemps que la ressource existe).
Il existe un quatrième type, une sorte de pointeur brut pour -shared_ptr
, appelé weak_ptr
. Vous l'utilisez pour faire référence à un shared_ptr
sans le posséder; vous pouvez ensuite vérifier si l'objet est toujours là et l'utiliser.
Le seul pointeur intelligent non propriétaire de la bibliothèque standard est std::weak_ptr
. Cependant, pour l'utiliser, l'objet propriétaire réel doit tenir la pointee dans un std::shared_ptr
.
Je suppose que vous avez utilisé std::unique_ptr
sur ceux d'avant. Si vous les convertissez en shared_ptr
maintenant, vous aurez l'avantage que vos pointeurs non propriétaires peuvent savoir que le pointeur propriétaire perdu est une référence tandis que les pointeurs bruts peuvent être laissés ballants sans aucune chance pour le composant non propriétaire de le détecter. Cependant, shared_ptr
entraînera une (très?) petite performance et surcharge de mémoire sur unique_ptr
.
Personnellement, je recommande d'utiliser un shared_ptr
et beaucoup weak_ptr
s au lieu d'un unique_ptr
et de nombreux pointeurs bruts dans le cas général et utilisez unique_ptr
si vous avez vraiment un problème de performances!