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