首先要理解什么是智能指针。
先来看普通指针,int *p = new int; 这个p 是一个普通指针,指向一个内存块,内存块中存放一个整形数值。
而智能指针是在普通指针的基础上,加上一个引用计数,它除了能指向一个内存块外,还多了一个功能,知道有多少个地方正在引用这个内存块。当没有地方用到这个内存块时,可以将这个内存块进行释放。
为什么要用智能指针呢?因为当有多处引用内存块时,不知道什么时候该删除指针所指的内存块,所以才引入智能指针。看下面的例子。
#include <iostream>
using namespace std;
void usePtr1(int *&p)
{
*p = 5;
cout << *p << endl;
delete p;
}
int main(int argc, char **argv)
{
int *p = new int;
usePtr1(p);
cout << *p << endl;
return 0;
}
上面代码存在问题,在main函数中new了一个int的内存,然后传递到usePtr1中使用,usePtr1用完这块内存后,觉得它不用了,就删掉了这块内存。结果导致main函数不能使用这块内存了。而且实际项目中,可能还有usePtr2, usePtr3, usePtrN函数都需要用到这块内存。
可能有的人说,我在main函数中new的,就在main函数中释放就可以了。像下面这样的。
void usePtr1(int *&p)
{
*p = 5;
cout << *p << endl;
}
int main(int argc, char **argv)
{
int *p = new int;
usePtr1(p);
cout << *p << endl;
delete p;
p = nullptr;
return 0;
}
这当然可以。但是有时候,new这块内存的函数,它也不知道什么时候释放这块内存。比如
int* getIntMemory()
{
return new int;
}
int main(int argc, char **argv)
{
int *p = getIntMemory();
*p = 5;
cout << *p << endl;
delete p;
return 0;
}
上面代码,内存是在getIntMemory函数中创建的,但是它本来创建这个内存块,就是供别人用的,所以它不能创建之后,就删了。只能在main函数中删除这个内存块。
那么现在问题来了,如果这个内存块被多个函数使用时,谁来释放这个内存块?
如上图所示,现在谁创建这个内存块已经不重要了,重要的是谁释放,应该是最后一个使用这个内存块的函数,来对内存块进行释放。每个函数用完之后,都切断这个函数与内存块的联系,然后在最后一个函数切断与内存块的联系之后,就需要释放这个内存块了。
智能指针就是通过引用计数,来表明有多少个地方在用这个内存块,当引用计数为零,也就是没用地方用到这个内存块了,就对这个内存块进行释放。