shared_ptr 循环引用以及解决办法
问题代码
#include <memory>
#include <stdio.h>
using namespace std;
class A;
class B
{
public:
B() { printf("B()\n"); }
~B() { printf("~B()\n"); }
void print(){ printf("B\n"); }
shared_ptr<A> ptrA_;
};
class A
{
public:
A() {printf("A()\n"); }
~A() { printf("~A()\n"); }
shared_ptr<B> ptrB_;
};
int main()
{
auto a = std::make_shared<A>();
auto b = std::make_shared<B>();
a->ptrB_ = b;
b->ptrA_ = a;
printf("user count:%d %d\n", a->ptrB_.use_count(), b->ptrA_.use_count());
return 0;
}
最后打印:
./a.out
A()
B()
user count:2 2
循环引用,内存泄漏
改进版本
使用
shared_ptr<A> ptrA_ 改为 weakptr<A> ptrA_
但是类里面无法使用ptrA_, 因为weakptr只有访问权限没有控制权限
如果需要控制ptrA_, 可以这样写:
in A:
void A::func() {
shared_ptr<B> b = ptrB_.lock();
if (nullptr != b) {
b->print();
}
}
in:B
void print() { printf("a good function B\n"); }
最终代码如下
#include <memory>
#include <stdio.h>
using namespace std;
class A;
class B
{
public:
B() { printf("B()\n"); }
~B() { printf("~B()\n"); }
void print() { printf("a good function B\n"); }
weak_ptr<A> ptrA_;
};
class A
{
public:
A() {printf("A()\n"); }
~A() { printf("~A()\n"); }
void func() {
shared_ptr<B> b = ptrB_.lock();
if (nullptr != b) { //这里很重要,来判断是否能拿到制作的控制权
b->print();
}
}
weak_ptr<B> ptrB_;
};
int main()
{
auto a = std::make_shared<A>();
auto b = std::make_shared<B>();
a->ptrB_ = b;
b->ptrA_ = a;
a->func();
printf("user count:%d %d\n", a->ptrB_.use_count(), b->ptrA_.use_count());
return 0;
}
打印如下:(无内存泄漏)
A()
B()
a good function B
user count:1 1
~B()
~A()
总结
在类设计中,如果一个类需要引用另一个类的实例,但不希望参与其生命周期管理(即不希望增加其引用计数),则应当使用std::weak_ptr。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
2023-01-13 如何重构一个超大的类[转载]
2021-01-13 uchar4