Operacje przenoszenia (takie jak konstruktor przenoszenia) std::shared_ptr
są 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_ptr
wywołaniu niepodzielnego zwiększenia liczby referencji (tj. Nie tylko ++RefCount
na składniku RefCount
danych całkowitych , ale np. Wywołanie InterlockedIncrement
w 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 sp
wartość, a następnie weźmiesz kopię wewnątrz CompilerInstance::setInvocation
metody, masz:
- Przy wejściu do metody
shared_ptr
parametr jest konstruowany jako kopia: ref count atomowy przyrost .
- Wewnątrz ciała danej metody jest, to skopiuj ten
shared_ptr
parametr w elemencie danych: Ref liczyć atomową przyrost .
- Po wyjściu z metody
shared_ptr
parametr 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_ptr
parametr według wartości, a następnie std::move
wewnątrz metody (tak jak zostało to prawidłowo zrobione w kodzie Clanga), masz:
- Przy wejściu do metody
shared_ptr
parametr jest konstruowany jako kopia: ref count atomowy przyrost .
- W treści metody
std::move
umieszczasz shared_ptr
parametr 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_ptr
parametr zostaje zniszczony; ale ponieważ przeszedłeś w kroku 2, nie ma nic do zniszczenia, ponieważ shared_ptr
parametr 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.