面试题答案
一键面试循环引用带来的问题
循环引用会导致内存泄漏。当两个对象通过std::shared_ptr
相互引用时,它们的引用计数永远不会归零,即使程序中不再有其他地方引用这两个对象,它们占用的内存也无法被释放。
解决循环引用的方法
- 使用
std::weak_ptr
:std::weak_ptr
是一种不控制对象生命周期的智能指针,它指向由std::shared_ptr
管理的对象,但不会增加对象的引用计数。当std::shared_ptr
管理的对象被释放后,指向它的std::weak_ptr
会自动失效。
#include <iostream>
#include <memory>
class B;
class A {
public:
std::shared_ptr<B> b_ptr;
~A() {
std::cout << "A destroyed" << std::endl;
}
};
class B {
public:
std::weak_ptr<A> a_weak_ptr;
~B() {
std::cout << "B destroyed" << std::endl;
}
};
- 手动打破循环:在适当的时候手动将其中一个
std::shared_ptr
设置为nullptr
,以打破循环引用。
#include <iostream>
#include <memory>
class B;
class A {
public:
std::shared_ptr<B> b_ptr;
~A() {
std::cout << "A destroyed" << std::endl;
}
};
class B {
public:
std::shared_ptr<A> a_ptr;
~B() {
std::cout << "B destroyed" << std::endl;
}
};
int main() {
std::shared_ptr<A> a = std::make_shared<A>();
std::shared_ptr<B> b = std::make_shared<B>();
a->b_ptr = b;
b->a_ptr = a;
// 手动打破循环
a->b_ptr = nullptr;
b->a_ptr = nullptr;
return 0;
}
当手动将a->b_ptr
和b->a_ptr
设置为nullptr
后,a
和b
的引用计数会归零,它们所占用的内存会被正确释放。