10.智能指针
10.1 unique_ptr
先看下面的代码:
#include <iostream>
using namespace std;
void Smart_pointer(int a);
int main(int argc, char ** argv)
{
Smart_pointer(1);
return 0;
}
void Smart_pointer(int a)
{
int * iptr = new int(a);
cout << "*iptr = " << *iptr << endl;
return;
}
当Smart_pointer函数执行完后,由于没有delete iptr(忘了写),因此iptr被销毁,而iptr指向的那块堆内存依旧存在,造成了内存泄漏。
注:当main函数执行完后,系统会自动清理堆空间;但是有的程序main函数会一直执行。
#include <iostream>
using namespace std;
void Smart_pointer(int a);
int main(int argc, char ** argv)
{
Smart_pointer(1);
return 0;
}
void Smart_pointer(int a)
{
int * iptr = new int(a);
cout << "*iptr = " << *iptr << endl;
//...发生异常...
delete iptr;
return;
}
当Smart_pointer函数未执行到delete处发生了异常,导致未释放堆空间造成内存泄漏。
注:在异常那一章讲解了这个问题,可以再catch和throw一次;但是不能每个函数都这么处理,这样太耗费资源。
#include <iostream>
using namespace std;
class SmartPointer {
private:
int * sp;
public:
SmartPointer():sp(NULL){}
SmartPointer(int * sp)
{
cout << "SmartPointer(int * sp)" << endl;
this->sp = sp;
}
~SmartPointer()
{
cout << "~SmartPointer()" << endl;
if (sp)
delete sp;
}
int operator*()
{
return *sp;
}
};
void Smart_pointer(int a);
int main(int argc, char ** argv)
{
Smart_pointer(1);
return 0;
}
void Smart_pointer(int a)
{
//int * iptr = new int(a);
//cout << "*iptr = " << *iptr << endl;
//delete iptr;
SmartPointer sp = new int(a);
cout << "*sp = " << *sp << endl;
return;
}
运行结果:
SmartPointer(int * sp)
*sp = 1
~SmartPointer()
执行了析构函数,使得sp被delete,即堆内存被释放。
为什么加上类SmartPointer 就可以了呢?
当执行SmartPointer sp = new int(a),实际分为2步:int * iptr = new int(a)和SmartPointer sp = iptr。当函数Smart_pointer执行完后,会销毁SmartPointer类的对象sp,调用sp类的析构函数,因此可以在析构函数中delete,这样会没有了内存泄漏问题。
其实在C++11的库中,提供一个智能指针模板unique_ptr,这样就不需要我们自己来提供智能指针。它需要包含头文件memory(被头文件iostream包含了)和使用名称空间std。
#include <iostream>
using namespace std;