《白话C++》第9章 泛型,Page847~849 AutoPtr 允许从外部指针构造

本文介绍了对AutoPtr结构的改进,使其能托管外部指针,包括默认构造、接管外部指针的构造、以及添加release和reset方法。讨论了如何正确使用和管理智能指针,以及可能的扩展如处理数组指针的需求。
摘要由CSDN通过智能技术生成

允许从外部指针构造

这个版本的AutoPtr仍然还有很多不完美的地方,比如它在构造函数中,一定要new出一个对象,因此无法表达一个“空指针”,也无法“接管”一个已经存在的外部指针,另外,两个(同质的)AutoPtr<T>对象之间,如何赋值,靠被也未实现。

托管外来指针

让它可以托工外来的指针,暂时只要修改它的构造函数即可:

template <typename T>
struct AutoPtr
{
    AutoPtr() //默认的构造过程
        : _ptr(nullptr) //_ptr将是一个空指针
    {}
    
    explicit AutoPtr(T* ptr) //构造时,接管一个外部的指针
        : _ptr(ptr)
    {}
    
    ...//析构及其他原有操作不变
};

现在,我们可以这样使用AutoPtr<T>了:

AutoPtr <S> sap;
sap->a = 10; //不要这样,会死的,sap._ptr当前是NULL.
S* s = new S; //用普通的方式,创建了s指针,后面的代码中,千万不能delete s
AutoPtr <S> sap2(s); //把s交给sap2管
AutoPtr <S> sap3(new S); //也可以直接接管一个匿名的指针
AutoPtr <S> sap4 = new S; //编译不通过,关键字explicit起的作用
S s2; //这家伙来自栈,将自动释放
AutoPtr <S> sap5(&s2); //编译通过,但后果自负

001行构造sap时,调用的是默认构造函数(无入参),sap的_ptr成员被初始化为nullptr,

002行,调用sap->a,相当于执行“0->a”。执行结果不定

003行,在外部创建一个S的“堆对象”,

004行,通过sap2对它进行托管,因此在后面的代码中千万不鞥delete s。

005行,是一个好做法,只要有可能,就争取在创建自动指针的同时创建外部指针,并且令其成为一个匿名的对象(没有变量承载),避免引入重复产出一个对象的问题。

006行,sap4构造失败,原因是“explicit”关键字起了作用。尽管我们所模仿的auto_ptr允许此类操作,但这里不考虑将一个T*对象直接赋值给AutoPtr<T>对象功能(那会引入许多更复杂的要求)。

007行的s2是一个“栈对象”,所以它总是会被自动释放内存,将它托付给一个只晓得“我一定要负责干掉它”的所谓的“智能指针”,会酿成大错。

允许改变指向

当AutoPtr持有一个指针之后,如何释放呢?

先来为AutoPtr增加一个离婚的首先,函数名叫“release”。

template <typename T>
T* AutoPtr <T>::release() //放手
{
    //放手, release,返回裸指针,智能指针不再占有内存
    T* you_are_free_now = _ptr;
    _ptr = nullptr;
    return you_are_free_now;
}

注意,所谓“放手”,是将AutoPtr原来拥有的_ptr “归还”回去,这样可以方便“离婚”后的_ptr独立存在:

AutoPtr <int> ap(new int);//结合
int* tmp = ap.release();//分手,曾经的_ptr现在是陌生的“tmp”

接下来,是再婚手续,为了合法,会先强制离婚:

template <typename T>
T* AutoPtr <T>::reset(T* new_ptr) 
{
    //智能指针开始管理新的裸指针,返回旧的裸指针
    T* old_ptr = release();
    _ptr = new_ptr;//由来只闻新人笑
    return old_ptr;//有谁听过旧人哭,旧人回娘家
}

设计一个完整的智能指针,所要考虑的事情远不止以上那些,比如:

如何判断智能指针是一个空指针?

如果比较两个智能指针?

如何在智能指针之间赋值?

【课堂作业】AutoPtr的实现

(1)根据以上代码,整理出一份相对完整,实际可用的AutoPtr,并写出配套的试用例子。

(2)考虑所写的AutoPtr是否支持处理数组指针,比如“AutoPtr <int> ap(new int [5])”,如果要支持,应如何改进?

  • 7
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值