web-dev-qa-db-fra.com

C ++ 11: remplacer tous les pointeurs bruts non propriétaires par std :: shared_ptr ()?

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?

57
kfmfe04

Personnellement, c'est ainsi que je le fais (plus ou moins):

  • nique_ptrs sont la propriété exclusive
  • pointeurs bruts signifie que celui qui m'a donné le pointeur brut garantit la durée de vie de cet objet pour correspondre ou dépasser ma durée de vie.
  • shared_ptrs sont pour la propriété partagée
  • faiblesse_ptrs sont pour quand un système veut vérifier si l'objet existe toujours avant de l'utiliser. C'est rare dans mon code car je trouve plus propre d'avoir un système garantissant la durée de vie de tout ce qu'il passe c'est des sous-systèmes (auquel cas j'utilise un pointeur brut)

J'utilise de loin plus d'unique_ptrs que de shared_ptrs, et plus de pointeurs bruts que de pointeurs faibles.

104
David

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.

11
GManNickG

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_ptrs 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!

8
ltjax