C++中智能指针一共有四种智能指针:
1、auto_ptr
,老式的,已被摒弃不用。这里提它是为做对比,以及被摒弃原因。
2、unique_ptr
,独占指针。
3、share_ptr
,共享指针。
4、weak_ptr
,弱指针。
要使用智能指针有两个基本点:
1、必须包含头文件memory:#include<memory>
2、智能指针模板位于名称空间std中:std::unique_ptr<...>...
直接举栗子说明基本用法:
#include <iostream>
#include <string>
#include <memory>
class Report
{
private:
std::string str;
public:
Report(const std::string s) : str(s) {}
~Report(){}
void comment() const {std::cout<<str<<std::endl;}
};
int main()
{
std::auto_ptr<Report> ps1 (new Report("using auto_ptr"));
std::unique_ptr<Report> ps2 (new Report("using unique_ptr"));
std::shared_ptr<Report> ps3 (new Report("using share_ptr"));
ps1->comment();
(*ps1).comment();
ps2->comment();
(*ps2).comment();
ps3->comment();
(*ps3).comment();
return 0;
}
输出:
using auto_ptr
using auto_ptr
using unique_ptr
using unique_ptr
using share_ptr
using share_ptr
格式上就是写上智能指针名,表征后面的变量为一个智能指针,然后在尖括号中传入指向的类型即可。
用法上跟普通指针没啥区别,解引用可以得到对象,->
可以调用方法。
上面演示的都是在创建的同时初始化,其实也可以只创建:std::unique_ptr<Report> ps2;
虽然这句没毛病,但是一般继续往后写就会瑕疵。。。
另外如上三种智能指针都要切记避免如下用法:
string vacation("I have a dream");
shared_ptr<string> pvac (&vacation);//严禁这样用!
因为pvac过期时候,delete将用于非堆内存(delete只能作用于堆内存),错误!其实后面还有用法总结(主要是跟new的关系),但这里的不能用于堆内存其实是根本原因。后面只是用法形式上的规定。
好,基本用法说完了,来说说为什么auto_ptr被摒弃,还是直接上代码:
auto_ptr<string> ps (new string ("I have a dream"));
auto_ptr<string> vocation;
vocation = ps;
OK ,很明了,两个指针进行了赋值。
假如,ps和vacation都是普通的指针,那么这两个指针指向了同一个对象,ps和vacation过期时,将删除一个对象两次,有问题!
这里用的是auto_ptr,肯定是比普通指针智能一点的,它能够将指针ps的指向权剥夺,然后赋给vocation。也就是说这句并不会报错。这句赋值过后,ps为空指针,vocation指向new的字符串。那么问题就来了,不报错,而且还遗留下一个空指针,是不是有种不祥的预感~~假如后面不小心写了这句呢?cout<<*ps<<endl;
完了,解引用了空指针,直接GG。
为了解决普通指针的俩指针指向同一对象问题和避免auto_ptr的遗留空指针隐患。大神们搞出来了unique_ptr和share_ptr。
unique_ptr:独占指针,也就是只有此指针能指向此对象,让其交出所有权时(比如不小心写的赋值等号),会报错。比如上方要是用unique_ptr的话,等号赋值那句就会报错:
unique_ptr<string> ps (new string ("I have a dream"));
unique_ptr<string> vocation;
vocation = ps;//由于是独占指针,让ps交出所有权时,这句就会报错。报错的目的其实是为了强制性要求不要这样用,强制性不让遗留下空指针,以免后患无穷。
当然你要说我就非得想这么用,就要让它交出所有权,调用std::move()就好了:
vocation = move(ps);
这样就不会报错了,实现了上面的功能,ps为空,vocaton取得了字符串对象所有权。如何证明呢?
cout<<*vocation;//只有这一句的话还是可以输出I have a dream的。
cout<<*ps;//但是这一句就不行了,不确定的行为。
share_ptr:利用引用计数,统计好指向同一对象的指针个数,当最后一个过期时才delete。
用上share_ptr后,应该直接等号赋值不会有问题吧:
shared_ptr<string> ps (new string ("I have a dream"));
shared_ptr<string> vocation;
vocation = ps;
cout<<*vocation<<endl;
cout<<*ps;
果不其然,没毛病:
I have a dream
I have a dream
可以发现,智能指针经常跟new鬼混在一起:
1、用unique_ptr必须用new或者new[]
2、用share_ptr必须为new,不能是new[]
看回上方严禁切记非法用法:
string vacation("I have a dream");
shared_ptr<string> pvac (&vacation);//严禁这样用!
是不是就是因为违反了这两条规则的原因呢??~~反正我是没看到一个new。。。