智能指针
众所周知,动态内存的管理是需要我们程序员自己手动操作的,一般是通过new和delete这一对运算符来完成的。而智能指针就是为了方便我们更好地管理内存空间,因为智能指针会自动地帮我们在使用完毕后释放指针的内存空间。这样的好处就在于可以避免有时我们忘记释放内存所导致的内存泄漏。
shared_ptr
shared_ptr就是智能指针中的一种,目前的标准库一般是有两种智能指针unique_ptr和shared_ptr,为了避免本文出现的循环引用问题,标准库还引入了一种weak_ptr。
unique_ptr和shared_ptr的不同就在于shared_ptr允许多个指针指向同一个对象,unique_ptr则是只允许一个指针指向一个对象,是“独占”式的指向。
循环引用
因为shared_ptr允许多个指针指向同一个对象,就无法避免地会存在A指向B,而B指向A的情况,在这种情况下就会导致shared_ptr无法正确地析构对象而导致内存泄漏。
#include<iostream>
#include<memory>
using namespace std;
class B;
class A{
public:
A(){
cout<<"A"<<endl;
}
~A(){
cout<<"delete A"<<endl;
}
shared_ptr<B>a_;
};
class B{
public:
B(){
cout<<"B"<<endl;
}
~B(){
cout<<"delete B"<<endl;
}
shared_ptr<A>b_;
};
int main()
{
shared_ptr<A>a=make_shared<A>();
shared_ptr<B>b=make_shared<B>();
a->a_=b;
b->b_=a;
cout<<a.use_count()<<endl;
cout<<b.use_count()<<endl;
return 0;
}
上述代码跑出的结果是
A
B
2
2
能看到析构函数并没有被调用,因为没有出现delete A或delete B。而use_count()是属于shared_ptr的成员函数,它显示的是当前shared_ptr指向同一对象的智能指针数量。
而要解决这个循环引用问题,就需要我们之前提到的weak_ptr。
weak_ptr是弱共享的智能指针,它一般指向shared_ptr指向的对象,但并不会增加use_count的计数。
所以如果要解决这种循环引用的现象,就把A,B类内的shared_ptr的成员变量换成weak_ptr。