Déplacements (comme le constructeur de déplacement) pour std::shared_ptr
sont bon marché car ils sont fondamentalement "vol de conseils" (de la source à la destination ; pour être plus précis, l'ensemble du 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, copie les opérations sur std::shared_ptr
invoquez atomique l'augmentation du nombre de références (c'est-à-dire qu'il ne s'agit pas uniquement de ++RefCount
sur un nombre entier RefCount
mais, par exemple, en appelant InterlockedIncrement
sous Windows), qui est plus coûteux que de simplement voler des pointeurs/états.
Il faut donc analyser en détail la dynamique du comptage des références dans ce cas :
// shared_ptr<CompilerInvocation> sp;
compilerInstance.setInvocation(sp);
Si vous passez sp
par valeur et ensuite prendre un copie à l'intérieur de la CompilerInstance::setInvocation
méthode, vous avez :
- Lors de l'entrée dans la méthode, le
shared_ptr
le paramètre est construit par copie : ref count atomique incrémenter .
- Dans le corps de la méthode, vous copie le site
shared_ptr
dans l'élément de données : ref count atomique incrémenter .
- À la sortie de la méthode, l
shared_ptr
le paramètre est détruit : ref count atomique décrémenter .
Vous avez deux incréments atomiques et un décrément atomique, pour un total de trois atomique opérations.
Au lieu de cela, si vous passez le shared_ptr
par valeur et ensuite std::move
à l'intérieur de la méthode (comme correctement fait dans le code de Clang), vous avez :
- Lors de l'entrée dans la méthode, le
shared_ptr
le paramètre est construit par copie : ref count atomique incrémenter .
- Dans le corps de la méthode, vous
std::move
le site shared_ptr
dans l'élément de données : ref count ne pas changement ! Vous ne faites que voler des pointeurs/états : aucune opération atomique coûteuse de comptage de ref n'est impliquée.
- À la sortie de la méthode, l
shared_ptr
est détruit ; mais comme vous vous êtes déplacé à l'étape 2, il n'y a rien à détruire, puisque le paramètre shared_ptr
ne pointe plus sur rien. Encore une fois, aucune décrémentation atomique ne se produit dans ce cas.
En résumé, dans ce cas, vous obtenez seulement un ref count atomic increment, c'est à dire juste un atome fonctionnement.
Comme vous pouvez le voir, c'est beaucoup meilleur que deux incréments atomiques plus un décrément atomique (pour un total de trois opérations atomiques) pour le cas de la copie.