说明
weak_ptr是C++中智能指针的一种,与shared_ptr配合使用,weak_ptr不对对象的生命周期进行管理,即它持有对象的引用但不增加对象的引用计数。这意味着weak_ptr的存在不会阻止其所指向的对象被销毁。
使用场景
防止循环引用
当两个对象互相持有对方的shared_ptr时,会导致引用计数永远不为零,从而引起内存泄漏。在这种情况下,可将其中一个对象持有对方的weak_ptr来解决循环引用问题。
代码演示:
#include <memory>
#include <iostream>
class B; // 前向声明
class A {
public:
std::shared_ptr<B> b_ptr;
~A() { std::cout << "A destroyed" << std::endl; }
};
class B {
public:
// 使用weak_ptr替代shared_ptr解决循环引用
std::weak_ptr<A> a_ptr;
~B() { std::cout << "B destroyed" << std::endl; }
};
int main() {
auto a = std::make_shared<A>();
auto b = std::make_shared<B>();
a->b_ptr = b;
b->a_ptr = a; // 不增加引用计数
// 此时,尽管A和B互相引用,但由于使用了weak_ptr,对象能够被正确销毁。
return 0;
}
这个例子中,即使A和B互相引用,当它们离开作用域时,都能被正确地销毁。这是因为B持有的是一个指向A的weak_ptr,不会增加A的引用计数。
临时访问共享资源
当你需要临时访问由shared_ptr管理的资源,但又不想拥有资源所有权时。通过weak_ptr,你可以在资源存在时访问它,而不会干扰资源的生命周期管理。
代码演示;
#include <iostream>
#include <memory>
class Resource {
public:
Resource() { std::cout << "Resource Acquired\n"; }
~Resource() { std::cout << "Resource Released\n"; }
void do_something() { std::cout << "Doing something\n"; }
};
int main() {
std::weak_ptr<Resource> weakResource;
{
auto sharedResource = std::make_shared<Resource>(); // 在这个作用域中创建资源
weakResource = sharedResource; // 把 shared_ptr 赋给 weak_ptr,用于监测资源
// 检查资源是否存在
if (auto tempShared = weakResource.lock()) { // 尝试将 weak_ptr 提升为 shared_ptr
tempShared->do_something(); // 资源存在,使用资源
} else {
std::cout << "Resource is no longer available\n";
}
} // 资源在这个作用域结束时被释放
// 再次检查资源是否存在
if (auto tempShared = weakResource.lock()) { // 尝试将 weak_ptr 提升为 shared_ptr
tempShared->do_something(); // 如果资源仍然存在,使用资源
} else {
std::cout << "Resource is no longer available\n"; // 资源已经被释放
}
return 0;
}
在这个例子中,Resource类代表一个需要被监测状态的资源。我们首先创建了一个类型为Resource的shared_ptr,并将其与一个weak_ptr相关联。weak_ptr不会增加资源的引用计数,因此不会影响资源的生命周期。
在第一个作用域内,我们通过weak_ptr的lock()方法尝试提升它为shared_ptr,以访问资源。因为资源此时仍然存在,所以提升操作成功,我们可以通过返回的shared_ptr安全地使用资源。
一旦第一个作用域结束,shared_ptr会被销毁,从而释放资源。此时,如果我们再次尝试通过weak_ptr提升来访问资源,操作将失败,因为资源已经不再存在。此时lock()方法会返回一个空的shared_ptr,这允许我们检测到资源已经被释放。
通过这种方式,weak_ptr可以被用作一种有效的机制,以监测和检查由shared_ptr管理的资源的状态。