shared_ptr循环依赖因相互强引用导致引用计数无法归零,造成内存泄漏;解决方法是使用weak_ptr打破循环,weak_ptr不增加引用计数,通过lock()安全访问对象,确保在无强引用时对象可被释放。

C++中
shared_ptr
weak_ptr
当我们谈论C++的智能指针,尤其是
shared_ptr
shared_ptr
解决方案
shared_ptr
shared_ptr
shared_ptr
shared_ptr
shared_ptr
立即学习“C++免费学习笔记(深入)”;
解决之道,就是引入
weak_ptr
weak_ptr
shared_ptr
weak_ptr
weak_ptr
lock()
shared_ptr
shared_ptr
lock()
shared_ptr
shared_ptr
以下是一个经典的循环依赖示例及其
weak_ptr
#include <iostream>
#include <memory>
#include <string>
class B; // 前向声明
class A {
public:
std::shared_ptr<B> b_ptr;
std::string name;
A(const std::string& n) : name(n) {
std::cout << "A " << name << " constructed." << std::endl;
}
~A() {
std::cout << "A " << name << " destructed." << std::endl;
}
void set_b(std::shared_ptr<B> b) {
b_ptr = b;
}
};
class B {
public:
// 循环依赖问题:这里如果也是 shared_ptr<A> a_ptr; 就会形成循环
// 解决方案:使用 weak_ptr<A>
std::weak_ptr<A> a_ptr;
std::string name;
B(const std::string& n) : name(n) {
std::cout << "B " << name << " constructed." << std::endl;
}
~B() {
std::cout << "B " << name << " destructed." << std::endl;
}
void set_a(std::shared_ptr<A> a) {
a_ptr = a;
}
void use_a() {
if (auto sharedA = a_ptr.lock()) { // 尝试获取 shared_ptr
std::cout << "B " << name << " is using A " << sharedA->name << std::endl;
} else {
std::cout << "B " << name << ": A is no longer available." << std::endl;
}
}
};
void create_circular_dependency() {
std::shared_ptr<A> a = std::make_shared<A>("Alpha");
std::shared_ptr<B> b = std::make_shared<B>("Beta");
// 建立相互引用
a->set_b(b);
b->set_a(a); // 这里B持有A的weak_ptr
std::cout << "A's ref count: " << a.use_count() << std::endl; // 此时为1 (因为b_ptr持有)
std::cout << "B's ref count: " << b.use_count() << std::endl; // 此时为1 (因为a_ptr持有)
b->use_a(); // B可以安全地使用A
} // a 和 b 在这里离开作用域,shared_ptr 被销毁
int main() {
create_circular_dependency();
std::cout << "End of main function." << std::endl;
// 如果没有使用 weak_ptr,A和B的析构函数将不会被调用,造成内存泄漏。
// 使用 weak_ptr 后,A和B会正确析构。
return 0;
}运行上述代码,你会看到A和B的析构函数被正确调用,表明内存得到了释放。关键在于,当
create_circular_dependency
a
b
shared_ptr
a
b_ptr
shared_ptr<B>
b
weak_ptr<A>
weak_ptr
a
a
b_ptr
b
b
shared_ptr
要真正理解
weak_ptr
shared_ptr
shared_ptr
shared_ptr
shared_ptr
weak_ptr
当一个
shared_ptr
shared_ptr
循环引用就发生在两个或多个对象彼此“强拥有”对方的时候。 举个例子:
class Parent;
class Child;
class Parent {
public:
std::shared_ptr<Child> child;
Parent() { std::cout << "Parent constructed." << std::endl; }
~Parent() { std::cout << "Parent destructed." << std::endl; }
};
class Child {
public:
std::shared_ptr<Parent> parent; // 问题所在:这里是 shared_ptr
Child() { std::cout << "Child constructed." << std::endl; }
~Child() { std::cout << "Child destructed." << std::endl; }
};
void create_problem() {
std::shared_ptr<Parent> p = std::make_shared<Parent>();
std::shared_ptr<Child> c = std::make_shared<Child>();
p->child = c; // Parent持有Child,Child的强引用计数变为2 (p->child 和 c)
c->parent = p; // Child持有Parent,Parent的强引用计数变为2 (c->parent 和 p)
std::cout << "Parent ref count: " << p.use_count() << std::endl; // 输出 2
std::cout << "Child ref count: " << c.use_count() << std::endl; // 输出 2
} // p 和 c 离开作用域当
create_problem
p
c
p
Parent
c->parent
c
Child
p->child
Parent
Child
shared_ptr
shared_ptr
weak_ptr
weak_ptr
weak_ptr
使用
weak_ptr
weak_ptr
weak_ptr::lock()
shared_ptr
shared_ptr
lock()
shared_ptr
shared_ptr
shared_ptr
lock()
shared_ptr
nullptr
shared_ptr
使用注意事项:
lock()
weak_ptr
weak_ptr
if (auto shared_obj = weak_ptr_instance.lock()) { ... }shared_ptr
weak_ptr
weak_ptr
Node
children
shared_ptr
children
Parent
weak_ptr
weak_ptr
weak_ptr
weak_ptr
weak_ptr
lock()
weak_ptr
weak_ptr
weak_ptr
operator*
operator->
shared_ptr
weak_ptr
shared_ptr
虽然
weak_ptr
shared_ptr
重新设计所有权关系: 这是最根本的策略。很多时候,循环依赖的出现,可能暗示着对象模型本身存在一些不清晰或不合理之处。
weak_ptr
weak_ptr
shared_ptr
weak_ptr
使用裸指针(极度谨慎): 在某些非常特殊且生命周期严格受控的场景下,可以考虑使用裸指针来打破循环。但这种做法风险极高,因为它完全放弃了智能指针提供的安全性。你必须100%确定:
事件/回调机制: 当对象之间需要相互通信但又不想建立直接的强引用时,可以考虑事件或回调机制。
shared_ptr
std::function
std::function
this
weak_ptr<A>
lock()
this
总的来说,
weak_ptr
shared_ptr
weak_ptr
weak_ptr
以上就是C++shared_ptr与循环依赖问题解决方法的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号