循环引用指的是使用多个智能指针 shared_ptr 时,出现了指针之间的相互指向,从而形成环的情况,类似于死锁现象,在这种情况下智能指针往往不能正常调用对象的析构函数,从而造成内存泄漏;
#include<iostream> #include<memory> using namespace std; template<typename T> class Node{ public: Node(const T& value) :_pPre(NULL) , _pNext(NULL) , _value(value) { cout << "Node() " << endl; } ~Node() { cout << "~Node()" << endl; cout << "this: " << this << endl; } shared_ptr<Node<T>> _pPre; shared_ptr<Node<T>> _pNext; T _value; }; void Funtest(){ shared_ptr<Node<int>> sp1(new Node<int>(1)); shared_ptr<Node<int>> sp2(new Node<int>(2)); cout << "sp1.use_count: " << sp1.use_count() << endl; cout << "sp2.use_count: " << sp2.use_count() << endl; sp1->_pNext = sp2; sp2->_pNext = sp1; cout << "sp1.use_count: " << sp1.use_count() << endl; cout << "sp2.use_count: " << sp2.use_count() << endl; } int main(){ Funtest(); return 0; }
shared_ptr 实现中可以得知,当我们知道了引用计数减为零时,析构时才会释放对象,而上述情况造成了一个僵局,就是当析构对象时先析构 sp2,但是 sp2 的空间 sp1还在使用,所以引用计数为 1,不释放,sp1 也是同理。这样就造成了死循环,最后谁也没释放,内存泄漏;
在实际编程过程中应该尽量避免出现智能指针之间相互指向的情况,如果避免不了就是用弱指针,weak_ptr 只使用,不增加计数,只要出了作用域就会自动析构。