Операции перемещения (например, конструктор перемещения) для std::shared_ptr
являются дешевыми , поскольку они в основном являются «крадящими указателями» (от источника к месту назначения; точнее, весь блок управления состоянием «украден» от источника к месту назначения, включая информацию о количестве ссылок) ,
Вместо этого операции копирования при std::shared_ptr
вызове увеличивают атомный счетчик ссылок (т.е. не только ++RefCount
для целочисленного RefCount
члена данных, но, например, при вызове InterlockedIncrement
в Windows), что дороже, чем просто кража указателей / состояний.
Итак, детально анализируя динамику подсчета ссылок в этом случае:
// shared_ptr<CompilerInvocation> sp;
compilerInstance.setInvocation(sp);
Если вы передаете sp
по значению, а затем берете копию внутри CompilerInstance::setInvocation
метода, у вас есть:
- При входе в метод
shared_ptr
параметр создается с помощью копии: ref count атомарный инкремент .
- Внутри тела метода, вы скопировать в
shared_ptr
параметр в элементе данных: ЗАДАНИЕ рассчитывать атомное приращение .
- При выходе из метода
shared_ptr
параметр разрушается: ref count атомарный декремент .
У вас есть два атомных приращения и один атомарный декремент, всего три атомарных операции.
Вместо этого, если вы передадите shared_ptr
параметр по значению, а затем std::move
внутри метода (как это правильно сделано в коде Кланга), вы получите:
- При входе в метод
shared_ptr
параметр создается с помощью копии: ref count атомарный инкремент .
- Внутри тела метода, вы параметр в элемент данных: исх счетчик ничего не изменится! Вы просто крадете указатели / состояния: дорогостоящие операции по подсчету атомных ссылок не требуются.
std::move
shared_ptr
- При выходе из метода
shared_ptr
параметр уничтожается; но поскольку вы перешли на шаге 2, уничтожать нечего, так как shared_ptr
параметр больше ни на что не указывает. Опять же, в этом случае не происходит атомного декремента.
Итог: в этом случае вы получаете только один атомный инкремент подсчета ссылок, т.е. только одну атомарную операцию.
Как вы можете видеть, это намного лучше, чем два атомарных приращения плюс один атомарный декремент (всего три атомарных операции) для случая копирования.