三个智能指针模板都定义了类似于指针的对象,可以将new获得的地址赋给这种对象。当智能指针过期时,其析构函数将使用delete来释放内存。因此,如果将new返回的地址赋给这些对象,将无需记住稍后释放这些内存:在智能指针过期时,这些内存的释放是自动的。
1. auto_ptr(C++98)
2. unique_ptr (C++11)
3. shared_ptr
- 智能指针与常规指针:
常规指针:
void demo1()
{
double * pd=new double;//#1
*pd=25.5; //#2
return;??#3
}
//说明:
//#1. 为pd和一个double值分配存储空间,保存地址;
//#2. 将值复制到动态内存中
//#3. 删除pd,值被保留在动态内存中
智能指针:
void demo2()
{
auto_ptr<double> ap(new double);//#1
*ap=25.5;//#2
return;//#3
}
//说明:
//#1. 为ap和一个double值分配存储空间,保存地址;
//#2. 将值复制到动态内存中
//#3. 删除ap,ap的析构函数释放内存
使用只能指针要包含头文件memory,其他两种智能指针定义:
#include <memory>
...
unique_ptr<double> pdu(new double);
shared_ptr<string> pss(new string);
//全部三种智能指针都应避免一点:
string v("hello_pc");
shared_ptr<string> pv(&v);//No!!!
因为pv过期时,程序将delete运算符用于非堆内存。
- 为何有三种智能指针?
auto_ptr<string> ps(new string("T ans"));
auro_ptr<string> va;
va=ps;
上述复制语句,如果两个指针都是常规的,指向同一对象。它会出现问题,因为程序试图删除一个对象两次,一次在ps过期的时候,一次在va过期的时候。
- 解决方法:
- 定义赋值运算符,两个指针指向不同的对象,一个是另一个的副本
- 建立所有权概念,对于特定对象,只有一个智能指针可拥有它,只有拥有对象的智能指针的构造函数会删除对象。然后,让赋值操作转让所有权。auto_ptr和unique_ptr的策略,后者更严格。
引用计数,赋值时,计数加1,而指针过期时,计数减1。仅当最后一个指针过期时,才用delete。shared_ptr的策略。
unique_ptr为何优于auto_ptr
auto_ptr<string> p1(new string("auto"));
auto_ptr<string> p2;
p2=p1;//#3
在语句#3,p2接管string对象的所有权后,p1的所有权被剥夺。但如果后续程序要用到p1, p1不再指向有效数据,这是个坏事。
unique_ptr<string> p1(new string("auto"));
unique_ptr<string> p2;
p2=p1;//#3
用unique_ptr指针,编译器认为#3非法,避免了p3不再指向有效的数据。
另外:auto_ptr使用delete而不是delete[],只能与new一起使用。
unique_ptr有使用new[]和delete[]的版本.
unique_ptr < double []> pda(new double(5));
智能指针的选择
如果程序要使用多个指向同一对象的指针,应选择shared_ptr。
如果不需要使用多个指向同一对象的指针,可使用unique_ptr。在满足unique_ptr的条件时,也可用auto_ptr,但unique_ptr更好。警告:
使用new分配内存时,才能使用auto_ptr和shared_ptr,使用new[]时,不能使用它们。