Verschiebungsoperationen (wie der Verschiebungskonstruktor) für std::shared_ptrsind billig , da sie im Grunde genommen "Zeiger stehlen" (von Quelle zu Ziel; genauer gesagt, der gesamte Statussteuerblock wird von Quelle zu Ziel "gestohlen", einschließlich der Referenzzählinformationen). .
Stattdessen erhöhen sich die Kopiervorgänge beim std::shared_ptrAufrufen der Anzahl der Atomreferenzen (dh nicht nur ++RefCountbei einem ganzzahligen RefCountDatenelement, sondern z. B. beim Aufrufen InterlockedIncrementvon Windows), was teurer ist als nur das Stehlen von Zeigern / Status.
Analyse der Ref-Count-Dynamik dieses Falls im Detail:
// shared_ptr<CompilerInvocation> sp;
compilerInstance.setInvocation(sp);
Wenn Sie einen spWert übergeben und dann eine Kopie innerhalb der CompilerInstance::setInvocationMethode erstellen, haben Sie:
- Bei der Eingabe der Methode wird der
shared_ptrParameter kopierkonstruiert: ref count atomares Inkrement .
- Innerhalb des Hauptteils der Methode kopieren Sie den
shared_ptrParameter in das Datenelement: ref count atomares Inkrement .
- Beim Beenden der Methode wird der
shared_ptrParameter zerstört: ref count atomares Dekrement .
Sie haben zwei atomare Inkremente und ein atomares Dekrement für insgesamt drei atomare Operationen.
Wenn Sie stattdessen den shared_ptrParameter als Wert und dann std::moveinnerhalb der Methode übergeben (wie in Clangs Code korrekt ausgeführt), haben Sie:
- Bei der Eingabe der Methode wird der
shared_ptrParameter kopierkonstruiert: ref count atomares Inkrement .
- Innerhalb des Methodenkörpers geben Sie
std::moveden shared_ptrParameter in das Datenelement ein: ref count ändert sich nicht ! Sie stehlen nur Zeiger / Status: Es sind keine teuren atomaren Ref-Count-Operationen erforderlich.
- Beim Beenden der Methode wird der
shared_ptrParameter zerstört. Aber seit Sie in Schritt 2 umgezogen sind, gibt es nichts zu zerstören, da der shared_ptrParameter auf nichts mehr zeigt. Auch in diesem Fall findet keine atomare Dekrementierung statt.
Fazit: In diesem Fall erhalten Sie nur ein Atominkrement für die Ref-Anzahl, dh nur eine Atomoperation .
Wie Sie sehen können, ist dies viel besser als zwei atomare Inkremente plus ein atomares Dekrement (für insgesamt drei atomare Operationen) für den Kopierfall.