为什么 shared_ptr
可以安全地在多个线程中共享?
循环引用
因为shared_ptr
std::shared_ptr
的引用计数是线程安全的。这意味着你可以在多个线程中安全地拷贝、赋值和销毁 std::shared_ptr
。然而,访问或修改 shared_ptr
所指向的对象时,需要额外的同步机制来确保线程安全。
循环引用:
两个
shared_ptr
对象如果互相指向同一个对象,它们的引用计数永远不会为零,这是因为每个shared_ptr
对象内部维护一个计数器(引用计数),用于跟踪有多少个shared_ptr
指向同一个对象。只有当所有指向该对象的shared_ptr
对象都被销毁或重置时,对象的引用计数才会归零,从而触发对象的析构函数调用,释放对象所占用的资源。
具体来说,如果有两个 shared_ptr
对象指向同一个对象,例如:
#include <memory>
#include <iostream>
class MyClass {
public:
MyClass() {
std::cout << "MyClass constructed\n";
}
~MyClass() {
std::cout << "MyClass destroyed\n";
}
};
int main() {
std::shared_ptr<MyClass> ptr1 = std::make_shared<MyClass>();
std::shared_ptr<MyClass> ptr2 = ptr1; // ptr2 指向 ptr1 所指向的对象
// 此时引用计数为 2
// 离开作用域时,ptr2 的析构函数调用,引用计数减一
// 离开作用域时,ptr1 的析构函数调用,引用计数减一,MyClass 对象被销毁
return 0;
}
在这个例子中,ptr1
和 ptr2
指向同一个 MyClass
对象。它们的引用计数在创建时为 1,当 ptr2
复制构造函数或赋值操作后,引用计数增加到 2。只有当 ptr1
和 ptr2
都离开其作用域或被显式地销毁时,MyClass
对象才会被销毁。
这种设计保证了当任何一个 shared_ptr
指向某个对象时,该对象都不会被提前释放,直到所有相关的 shared_ptr
都不再指向它。