第16章part2-智能指针

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。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值