Operacje przenoszenia (takie jak konstruktor przenoszenia) std::shared_ptrsą tanie , ponieważ w zasadzie są „wskaźnikami kradzieży” (ze źródła do celu; dokładniej mówiąc, cały blok kontroli stanu jest „skradziony” od źródła do celu, w tym informacje o liczbie referencyjnej) .
Zamiast tego operacje kopiowania przy std::shared_ptrwywołaniu niepodzielnego zwiększenia liczby referencji (tj. Nie tylko ++RefCountna składniku RefCountdanych całkowitych , ale np. Wywołanie InterlockedIncrementw systemie Windows) jest droższe niż zwykła kradzież wskaźników / stanu.
Tak więc, analizując szczegółowo dynamikę liczby ref w tym przypadku:
// shared_ptr<CompilerInvocation> sp;
compilerInstance.setInvocation(sp);
Jeśli przekażesz spwartość, a następnie weźmiesz kopię wewnątrz CompilerInstance::setInvocationmetody, masz:
- Przy wejściu do metody
shared_ptrparametr jest konstruowany jako kopia: ref count atomowy przyrost .
- Wewnątrz ciała danej metody jest, to skopiuj ten
shared_ptrparametr w elemencie danych: Ref liczyć atomową przyrost .
- Po wyjściu z metody
shared_ptrparametr zostaje zniszczony: ref count atomic decment .
Masz dwa atomowe przyrosty i jeden atomowy dekrement, co daje w sumie trzy atomowe operacje.
Zamiast tego, jeśli przekażesz shared_ptrparametr według wartości, a następnie std::movewewnątrz metody (tak jak zostało to prawidłowo zrobione w kodzie Clanga), masz:
- Przy wejściu do metody
shared_ptrparametr jest konstruowany jako kopia: ref count atomowy przyrost .
- W treści metody
std::moveumieszczasz shared_ptrparametr w składniku danych: liczba ref nie zmienia się! Po prostu kradniesz wskaźniki / stan: nie są zaangażowane żadne kosztowne atomowe operacje liczenia referencji.
- Podczas wychodzenia z metody
shared_ptrparametr zostaje zniszczony; ale ponieważ przeszedłeś w kroku 2, nie ma nic do zniszczenia, ponieważ shared_ptrparametr już na nic nie wskazuje. Ponownie, w tym przypadku nie dochodzi do dekrementacji atomowej.
Konkluzja: w tym przypadku otrzymujesz tylko jeden atomowy przyrost liczby ref, tj. Tylko jedną atomową operację.
Jak widać, jest to znacznie lepsze niż dwa atomowe przyrosty plus jeden atomowy dekrement (w sumie trzy atomowe operacje) dla wielkości kopii.