参考资料:《C++ Primer Plus中文版 第六版》
智能指针定义:
行为类似于指针的类对象,但这种对象还有其他功能。重要的区别是他负责自动释放所指向的对象。
引入智能指针的原因:
在C++中,动态内存分配使用new、delete或new[]、delete[]创建和销毁,但会出现使用new或new[]创建动态内存后,忘记使用delete或delete[]或在使用delete之前程序异常终止,造成内存泄露。或者在还有指针引用该内存时提前使用delete释放内存,会产生引用非法内存指针问题。为此,C++11提出了智能指针概念。
智能指针模板类:
可帮助管理动态内存的智能指针模板有:auto_ptr、unique_ptr、share_ptr和weak_ptr;这四个智能指针模板都定义了类似指针的对象,可以将new获得的地址赋给这种对象,当智能指针过期时,其析构函数将使用delete来释放内存。
#include <memory>
void remodel(std::string & str)
{
std::auto_ptr<std::string> ps (new std::string(str));
...
if(weird_thing())
throw exception();
str = *ps;
return;
}
auto_ptr
模板auto_ptr是C++98提供的解决方案,C++11已将其摒弃.
auto_ptr<string> ps (new string("I reigned lonely as a cloud."));
auto_ptr<string> vocation;
vocation = ps;
如果ps和vocation是常规指针,则两个指针将指向同一个string对象,当ps过期时,程序将释放该对象,但是vocation过期时,程序也将释放这个对象,要避免这种问题,方法有多种:
1、定义赋值运算符,使之执行深复制,这样两个指针将指向不同的对象,其中的一个对象是另一个对象的副本。
2、建立所有权概念,对于特定的对象,只能有一个智能指针可拥有它,这样只有拥有对象的智能指针的构造函数会删除对象。然后,让赋值操作转让所有权。这就是用于auto_ptr和unique_ptr的策略。但unique_ptr的策略更严格。
3、创建智能更高的指针,跟踪引用特定对象的智能指针数,这称为引用计数,赋值时,技术将加1,而指针国旗时,计数将减1。仅当最后一个指针过期时,才调用delete。这是share_ptr采用的策略。
unique_ptr为何优于auto_ptr
auto_ptr<string> p1(new string("auto");
auto_ptr<string> p2;
p2 = p1;
p2接管string对象的所有权后,p1的所有权被剥夺,但如果程序随后试图使用p1时程序可能会出现崩溃现象。
unique_ptr<string> p3 = new string("auto");
unique_ptr<string> p4;
p4 = p3; //ERROR
该段程序在编译的时候报错,避免了p3不再指向有效数据的问题,因此,unique_ptr比auto_ptr更安全。
相比于auto_ptr和share_ptr,unique_ptr有可用于数组的变体。
std::unique_prt<double[]> pda(new double(5));
weak_ptr
weak_ptr解决了share_ptr循环引用的问题,它是一种不控制所指向对象生存期的智能指针,不能直接将它用来定义一个智能指针,智能配合share_ptr。将一个weak_ptr绑定到一个shared_ptr不会改变shared_ptr的引用计数。一旦最后一个指向对象的shared_ptr被销毁,对象就会被释放,即使有weak_ptr指向对象,对象还是会被释放。
选择智能指针
如果程序要使用多个指向同一个对象的指针,应选择share_ptr。
如果程序不需要多个指向同一个对象的指针,则可使用unique_ptr。
如果程序不适用new或new[]分配内存时,则不能使用unique_ptr。
如果程序不使用new分配内存,则不能使用auto_ptr和share_ptr。