Les opérations de déplacement (comme le constructeur de déplacement) pour std::shared_ptr
sont bon marché , car ce sont essentiellement des "pointeurs de vol" (de la source à la destination; pour être plus précis, tout le bloc de contrôle d'état est "volé" de la source à la destination, y compris les informations de comptage de référence) .
Au lieu de cela, copiez les opérations sur std::shared_ptr
invoquer l' augmentation du nombre de références atomiques (c'est-à-dire pas seulement ++RefCount
sur un RefCount
membre de données entier , mais par exemple en appelant InterlockedIncrement
sur Windows), ce qui est plus coûteux que de simplement voler des pointeurs / état.
Donc, en analysant la dynamique du nombre de ref de ce cas en détail:
// shared_ptr<CompilerInvocation> sp;
compilerInstance.setInvocation(sp);
Si vous passez sp
par valeur puis en prenez une copie à l'intérieur de la CompilerInstance::setInvocation
méthode, vous avez:
- Lors de la saisie de la méthode, le
shared_ptr
paramètre est construit par copie: ref count incrément atomique .
- Dans le corps de la méthode, vous copiez le
shared_ptr
paramètre dans le membre de données: ref count atomic increment .
- A la sortie de la méthode, le
shared_ptr
paramètre est détruit: ref count décrément atomique .
Vous avez deux incréments atomiques et un décrément atomique, pour un total de trois opérations atomiques .
Au lieu de cela, si vous passez le shared_ptr
paramètre par valeur, puis std::move
à l'intérieur de la méthode (comme correctement fait dans le code de Clang), vous avez:
- Lors de la saisie de la méthode, le
shared_ptr
paramètre est construit par copie: ref count incrément atomique .
- Dans le corps de la méthode, vous placez
std::move
le shared_ptr
paramètre dans le membre de données: le nombre de références ne change pas ! Vous ne faites que voler des pointeurs / état: aucune opération coûteuse de comptage de références atomiques n'est impliquée.
- Lorsque vous quittez la méthode, le
shared_ptr
paramètre est détruit; mais comme vous vous êtes déplacé à l'étape 2, il n'y a rien à détruire, car le shared_ptr
paramètre ne pointe plus vers rien. Encore une fois, aucun décrément atomique ne se produit dans ce cas.
Bottom line: dans ce cas, vous obtenez un seul incrément atomique de ref count, c'est-à-dire une seule opération atomique .
Comme vous pouvez le voir, c'est bien mieux que deux incréments atomiques plus un décrément atomique (pour un total de trois opérations atomiques) pour le cas de copie.