Las operaciones de movimiento (como el constructor de movimientos) std::shared_ptr
son baratas , ya que básicamente son "robo de punteros" (de origen a destino; para ser más precisos, todo el bloque de control de estado es "robado" de origen a destino, incluida la información de recuento de referencia) .
En cambio, las operaciones de copia en std::shared_ptr
invocación aumentan el recuento de referencia atómica (es decir, no solo ++RefCount
en un RefCount
miembro de datos enteros , sino, por ejemplo, InterlockedIncrement
en Windows), que es más costoso que simplemente robar punteros / estado.
Entonces, analizando la dinámica de recuento de ref de este caso en detalle:
// shared_ptr<CompilerInvocation> sp;
compilerInstance.setInvocation(sp);
Si pasa sp
por valor y luego toma una copia dentro del CompilerInstance::setInvocation
método, tiene:
- Al entrar en el método, los
shared_ptr
es un parámetro copia construidos: ref contar atómica de la subasta .
- Dentro del cuerpo del método, copie el
shared_ptr
parámetro en el miembro de datos: incremento atómico de recuento de referencia .
- Al salir del método, el
shared_ptr
parámetro se destruye: decremento atómico de recuento de ref .
Tiene dos incrementos atómicos y un decremento atómico, para un total de tres operaciones atómicas .
En cambio, si pasa el shared_ptr
parámetro por valor y luego std::move
dentro del método (como se hace correctamente en el código de Clang), tiene:
- Al entrar en el método, los
shared_ptr
es un parámetro copia construidos: ref contar atómica de la subasta .
- Dentro del cuerpo del método, ingresa
std::move
el shared_ptr
parámetro en el miembro de datos: ¡el recuento de referencias no cambia! Solo está robando punteros / estado: no hay operaciones costosas de conteo de ref.
- Al salir del método, el
shared_ptr
parámetro se destruye; pero como te moviste en el paso 2, no hay nada que destruir, ya que el shared_ptr
parámetro ya no apunta a nada. Una vez más, no se produce una disminución atómica en este caso.
En pocas palabras: en este caso, obtienes solo un incremento atómico de recuento de referencia, es decir, solo una operación atómica .
Como puede ver, esto es mucho mejor que dos incrementos atómicos más un decremento atómico (para un total de tres operaciones atómicas) para el caso de copia.