C++的内存管理是一个很大的问题,C++程序员总是会无意间的造成内存泄漏的问题,C++98给出了智能指针的解决方案,智能指针会在销毁指针的时候自动销毁指针指向的内容(例如栈解退)。
智能指针是一个模板类,可以看成一个被包装过的指针。他的构造函数如下
template
class auto_ptr
{
public:
explicit auto_ptr(X * p=0) throw() {}
};
他将获得一个指向X的指针。
使用智能指针后的程序
#include
#include
#include
using namespace std;
int main()
{
auto_ptr ps(new string ("hello"));
//don't need delete
cout << *ps;
return 0;
}
运行结果
在只能指针ps被销毁的时候,会调用其析构函数释放ps指向的内容。
我们也可以写一个自己的简单的智能指针
include
#include
#include
using namespace std;
template
class my_auto_ptr
{
private:
T * ptr;
public:
explicit my_auto_ptr(T * p= nullptr) : ptr(p) {}
~my_auto_ptr()
{
delete ptr;
}
T & operator*()
{
return *ptr;
}
};
int main()
{
my_auto_ptr ps (new string("hello"));
cout << *ps;
return 0;
}
想进一步包装的话还可以重载-> =等运算符。
这种智能指针(auto_ptr)在进行赋值运算时可能会有问题,又或者是不经意间重复释放内存,有以下几种解决方案
1.重载=进行深拷贝
2.建立所有权的概念,每个对象只有一个智能指针拥有它,=是所有权的转让
unique_ptr
3.创建智能性更高的指针,记录构造函数和析构函数的次数,判断是否释放。
shared_ptr
unique_ptr的使用比较严格
编译器不允许将将这类对象赋值给另一个对象,但如果对象是一个临时的右值则可以(如返回值)。
int main()
{
unique_ptr ps;
unique_ptr pd;
pd = ps; //error
return 0;
}
这样可以,这将"hello"的所有权从temp变成了主函数中的ps
unique_ptr t(const char * s)
{
unique_ptr temp(new string(s));
return temp;
}
int main()
{
unique_ptr ps;
ps = t("hello");
cout << *ps;
return 0;
}
注意:智能指针的本质也是使用new和delete,其中,只有unique_ptr有[]delete的版本,不要让只能指针指向非new出来的对象。
在unique_ptr为右值时,可将其赋值给shared_ptr,因为后者是计数处理。
shared_ptr有一个构造函数,可将右值unique_prt转换为shared_prt,shared_ptr将接管原来unique_prt接管的对象。
智能指针的选择
如果要将多个指针指向同一个对象,应选择shared_ptr
SLT很多算法都支持赋值和赋值操作,可用于shared_prt
不需要用多个指针指向同一个对象, 可使用unique_ptr
用new分配的内存,并返回该内存的指针,unique_prt是个不错的选择