c++11——share_ptr的助手weak_ptr
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
- 一.weak_ptr简介
- 与share_ptr的区别
- 二.解决场景
- 1.循环引用
- 错误场景
- 解决问题
- 2.观察者功能
一.weak_ptr简介
-
weak_ptr 是 C++ 标准库中的一个智能指针类,它是 share_ptr 的一个辅助类,用于实现弱引用,从而避免循环引用和内存泄漏等问题。
-
weak_ptr 的设计目的是为了实现对对象的弱引用,即不阻止对象被销毁,也不保证对象的生命周期。它通过使用 weak_ptr 指针来跟踪对象的生命周期,当对象被销毁时,weak_ptr 会自动释放所占用的资源。
-
weak_ptr 的主要用途是实现弱引用,从而避免循环引用和内存泄漏等问题。在某些情况下,例如多线程编程中,使用 weak_ptr 可以避免因为循环引用而导致的死锁问题。
-
weak_ptr 的使用方法与 share_ptr 类似,但是它不能直接使用 * 和 -> 操作符来访问对象,需要使用 lock() 方法来获取一个 share_ptr 指针,从而访问对象。
-
成员函数use_count() 观测资源引用计数
-
成员函数expired() 功能相当于 use_count()==0 表示被观测的资源(也就是shared_ptr的管理的资源)是否被销毁
-
成员函数lock()从被观测的shared_ptr获得一个可用的shared_ptr对象, 进而操作资源。但当expired()==true的时候,lock()函数将返回一个存储空指针的shared_ptr
-
std: :weak_ptr 一般者是通过 std: : shared _ptr 来创建的
与share_ptr的区别
- shared_ptr 用于管理对象的生命周期,而 weak_ptr 用于观察对象的生命周期
- weak_ptr不会改变资源的引用计数,只是一个观察者的角色,通过观察shared_ptr来判定资源是否存在
- weak_ptr持有的引用计数,不是资源的引用计数,而是同一个资源的观察者的计数
- weak_ptr没有提供常用的指针操作,无法直接访问资源,需要先通过lock方法提升为shared_ptr强智能指针,才能访问资源
二.解决场景
1.循环引用
错误场景
循环引用是指两个或多个对象相互引用对方,导致它们之间的引用关系无法解除,从而导致内存泄漏等问题。
在 C++ 中,循环引用通常是由于使用 share_ptr
或 weak_ptr
等智能指针类时,没有正确处理对象之间的引用关系导致的。例如,下面的代码就创建了一个循环引用:
#include <iostream>
#include <memory>class MyClass {
public:MyClass() {std::cout << "Constructor called." << std::endl;}~MyClass() {std::cout << "Destructor called." << std::endl;}std::shared_ptr<MyClass> ptr;
};int main() {std::shared_ptr<MyClass> sp1(new MyClass);std::shared_ptr<MyClass> sp2(new MyClass);sp1->ptr = sp2;sp2->ptr = sp1;return 0;
}
在这个例子中,我们创建了两个 MyClass
的对象 sp1
和 sp2
,并将它们相互引用。
当 main
函数结束时,sp1
和 sp2
的引用计数都为 1,因此它们都无法被销毁,从而导致循环引用。
解决问题
#include <iostream>
#include <memory>class MyClass {
public:MyClass() {std::cout << "Constructor called." << std::endl;}~MyClass() {std::cout << "Destructor called." << std::endl;}std::weak_ptr<MyClass> ptr;
};int main() {std::shared_ptr<MyClass> sp1(new MyClass);std::shared_ptr<MyClass> sp2(new MyClass);sp1->ptr = sp2;sp2->ptr = sp1;return 0;
}
在这个例子中,我们创建了两个 MyClass
的对象 sp1
和 sp2
,并将它们相互引用。但是,我们使用 std::weak_ptr<MyClass>
,不会影响sp1
和sp2
的强引用计数,当 main
函数结束时,sp1
和 sp2
的引用计数都为 0,因此它们都被销毁,从而避免了循环引用。
2.观察者功能
#include <iostream>
#include <memory>class MyClass {
public:MyClass() { std::cout << "MyClass Constructor" << std::endl; }~MyClass() { std::cout << "MyClass Destructor" << std::endl; }void display() const { std::cout << "Displaying MyClass" << std::endl; }
};int main() {std::shared_ptr<MyClass> sp = std::make_shared<MyClass>();std::weak_ptr<MyClass> wp = sp; // 创建weak_ptr// 检查weak_ptr是否有效if (auto temp_sp = wp.lock()) {temp_sp->display();} else {std::cout << "The object has been destroyed." << std::endl;}sp.reset(); // 释放shared_ptr,MyClass对象被销毁// 再次检查weak_ptr是否有效if (auto temp_sp = wp.lock()) {temp_sp->display();} else {std::cout << "The object has been destroyed." << std::endl;}return 0;
}