使用/取消引用shared_ptr几乎就像访问原始 ptr,与常规指针访问相比,锁定weak_ptr是一个性能“重”的操作,因为如果另一个线程触发释放,此代码必须是“线程感知的”才能正常工作指针引用的对象。至少,它必须执行某种互锁/原子操作,根据定义,这种操作比常规内存访问要慢得多。
像往常一样,查看发生了什么的一种方法是检查生成的代码:
#include <memory>
class Test
{
public:
void test();
};
void callFuncShared(std::shared_ptr<Test>& ptr)
{
if (ptr)
ptr->test();
}
void callFuncWeak(std::weak_ptr<Test>& ptr)
{
if (auto p = ptr.lock())
p->test();
}
void callFuncRaw(Test* ptr)
{
if (ptr)
ptr->test();
}
通过 shared_ptr 和原始指针访问是一样的。由于shared_ptr
作为引用传递,我们需要加载引用的值,这就是为什么不同之处只是 shared_ptr 版本的额外加载。
调用函数共享:

调用函数弱:

通过调用weak_ptr
会产生 10 倍以上的代码,并且充其量它必须经过锁定的比较交换,这本身将比取消引用 raw 或 shared_ptr 花费 10 倍以上的 CPU 时间:

只有当共享计数器不为零时,它才能加载指向实际对象的指针并使用它(通过调用对象或创建一个shared_ptr
)。