scoped_ptr
ne peut pas être copié et est supprimé de la portée. C'est donc un peu limité shared_ptr
. Il semble d'ailleurs que les cas où vous avez vraiment besoin de restreindre l'opération de copie shared_ptr
est préférable d'utiliser. Parce que parfois vous ne savez pas que vous devez créer une copie de votre objet ou non. La question est donc la suivante: outre les cas mentionnés ci-dessus, pourrait-on considérer que shared_ptr
est préférable (ou recommandé) d'utiliser au lieu de scoped_ptr
. Est-ce que scoped_ptr
fonctionne beaucoup plus rapidement à partir de shared_ptr
, ou a-t-elle des avantages?
Merci!
shared_ptr
est plus lourd que scoped_ptr
. Il doit allouer et libérer un objet de comptage de référence ainsi que l'objet géré, et pour gérer le comptage de références thread-safe - sur une plate-forme sur laquelle j'ai travaillé, cela représentait une surcharge importante.
Mon conseil (en général) est d'utiliser l'objet le plus simple qui répond à vos besoins. Si vous avez besoin d'un partage compté par référence, utilisez shared_ptr
; si vous avez juste besoin d'une suppression automatique une fois que vous avez terminé avec une seule référence, utilisez scoped_ptr
.
Performance - shared_ptr
a plus de fonctionnalités, mais nécessite également une allocation supplémentaire (elle est également plus grande, mais cela importe rarement).
[edit] La deuxième allocation peut être évitée en utilisant make_shared
, mais alors weak_ptr
conservera l'intégralité de l'allocation même après la destruction de l'objet, ce qui peut être un problème pour les gros objets.
Expresison of Intent utilisant scoped_ptr
vous indiquez plus explicitement ce que vous voulez faire. (Au cas où vous vous demandez - c'est une bonne chose :)). Si vous le faites correctement, shared_ptr indiquera également "cet objet est destiné à vivre au-delà de cette portée"
Leur objectif est différent, donc, dans de nombreux cas, "shared_ptr vs scoped_ptr" n'est pas du tout une question. Bien sûr, vous pouvez utiliser un shared_ptr lorsque tout ce dont vous avez besoin est un scoped_ptr. Mais à quoi ça sert? shared_ptr a probablement un surcoût légèrement plus important avec tous les comptages de références impliqués.
scoped_ptr
fonctionne beaucoup plus rapidement à partir de shared_ptr
. C'est juste. shared_ptr
alloue toujours la mémoire à l'aide de votre allocateur ou de l'allocateur par défaut.
Scoped_ptr a peu en commun avec shared_ptr, faiblesse_ptr ou unique_ptr car il ne fait que des cas très particuliers de "comptage de références". Ce n'est pas quelque chose dont vous aurez besoin très souvent dans un code bien conçu, mais c'est un bon outil à disposition.
Fondamentalement, un scoped_ptr n'est pas une chose comptée par référence du tout. Il s'agit plutôt d'un objet que vous créez sur la pile (dans la portée locale) afin que vous puissiez faire quelque chose comme ceci:
//Some enclosing scope- anything set off by "{}" or even a function:
{
scoped_ptr<MyObject> ptr = new MyObject( parameters...);
} // When we hit this closing brace, "ptr" will delete the "MyObject" inside.
Vous avez tendance à voir ce modèle plus avec des mutex et d'autres primitives de synchronisation - je peux déclarer un "AutoLock" qui verrouillera le mutex qui y est passé, puis le déverrouillera lors de sa suppression pour transformer toute la portée "{}" en une section critique.
Notez également qu'un 'scoped_ptr' n'a de sens que lorsque vous ne pouvez pas simplement faire une allocation de pile simple comme "MyObject obj (params ..)" pour une raison quelconque. Après tout, il vous permet d'utiliser un objet alloué par segment de mémoire comme s'il en était un sur la pile. Cela tend à être un cas d'utilisation beaucoup plus rare que le comptage de références de shared_ptr et de ses cousins.