欢迎交流 QQ 2431173627 微信 ccc17862701790
本系列的上一篇文章讲了手动方式的内存管理 new delete
这种方式往往存在很多问题 这一节将讲通过智能指针来自动管理动态内存
智能指针的引入
智能指针的引入有以下几大原因
1.在动态内存管理中,如果new上一块空间,但是没有delete,就会产生内存泄露的问题。
2.但是有时候,我们new了,也delete了,但是还会出现问题。例如在new和delete之间调用了某个抛异常的函数,就有可能导致没有执行delete。
例如:fun2里面使用了new[],最后也使用了delete[],看着没有问题,但是在new和delete之间调用了fun1,而fun1里面抛了异常,但是在fun2的delete之前并没有捕获,就会导致delete没有执行,仍然会有内存泄露的问题。
void fun1()
{
throw int(11);
}
void fun2()
{
int* p = new int[10000];
fun1();
delete[] p;
}
int main()
{
try
{
fun2();
}
catch (int& e)
{
cout << "捕获" << endl;
}
system("pause");
return 0;
}
如果想要解决上面的问题,有一种方法:就是如果发现delete之前发现某个函数抛出了异常,就在delete之前捕获这个异常,并且在catch语句里面进行资源的释放,并且可以再将这个异常重新抛出。
void fun2()
{
int* p = new int[10000];
try
{
fun1();
}
catch(int& e)
{
delete[] p;
cout << "重新抛出" << endl;
throw;
}
delete[] p;
}
但是这种方法写着比较繁琐,而且如果代码很多,就有可能忘记哪个函数抛出了异常,会防不胜防。
3.还有一种场景就是内存空间是delete释放了以后 但是指针没有置NULL (delete是不会把指针自动置为null的) 这样是野指针
3.因此,只要有一种方法,能够在出了作用域之后能够自动释放掉申请的空间,就会让空间得到正确的释放。而一个对象出了作用域会自动调用自己的析构函数,只要在析构函数里能够释放自己开辟的空间,就能达到目的。
4.智能指针就有上面的作用,能够自动的管理指针所指向的动态资源的释放。它不仅有着RAII的思想还能够像指针一样。(RAII:分配资源即初始化,即构造函数分配资源和初始化资源,在析构函数清理资源。像指针一样:能够解引用)。
5.智能指针实质上就是一个模板类,成员变量包含一个任意类型的指针,构造函数获得资源并初始化,析构函数清理资源。
注意:智能指针只能管理动态开辟的空间。
智能指针的发展历史
C++98时代的智能指针
Boost库的智能指针