As operações de movimentação (como o construtor de movimentação) std::shared_ptr
são baratas , pois basicamente são "indicadores de roubo" (da origem para o destino; para ser mais preciso, todo o bloco de controle de estado é "roubado" da origem para o destino, incluindo as informações da contagem de referência) .
Em vez disso, as operações de cópia ao std::shared_ptr
invocar o aumento da contagem de referência atômica (ou seja, não apenas ++RefCount
em um RefCount
membro de dados inteiro , mas, por exemplo, chamando o InterlockedIncrement
Windows), que é mais caro do que apenas roubar ponteiros / estado.
Portanto, analisando a dinâmica da contagem de ref deste caso em detalhes:
// shared_ptr<CompilerInvocation> sp;
compilerInstance.setInvocation(sp);
Se você passar sp
por valor e tirar uma cópia dentro do CompilerInstance::setInvocation
método, você terá:
- Ao inserir o método, o
shared_ptr
parâmetro é construído com cópia: ref count incremento atômico .
- Dentro do corpo do método, você copia o
shared_ptr
parâmetro no membro de dados: ref count incremento atômico .
- Ao sair do método, o
shared_ptr
parâmetro é destruído: ref count decrement atomic .
Você tem dois incrementos atômicos e um decréscimo atômico, para um total de três operações atômicas .
Em vez disso, se você passar o shared_ptr
parâmetro por valor e depois std::move
dentro do método (conforme feito corretamente no código de Clang), você terá:
- Ao inserir o método, o
shared_ptr
parâmetro é construído com cópia: ref count incremento atômico .
- Dentro do corpo do método, você
std::move
o shared_ptr
parâmetro no membro de dados: ref count não muda! Você está apenas roubando ponteiros / estado: não há operações caras de contagem atômica de ref.
- Ao sair do método, o
shared_ptr
parâmetro é destruído; mas desde que você avançou na etapa 2, não há nada para destruir, pois o shared_ptr
parâmetro não está mais apontando para nada. Novamente, nenhum decréscimo atômico acontece neste caso.
Conclusão: neste caso, você obtém apenas um incremento atômico de contagem de ref, ou seja, apenas uma operação atômica .
Como você pode ver, isso é muito melhor do que dois incrementos atômicos mais um decréscimo atômico (para um total de três operações atômicas) para o caso da cópia.