C++智能指针(二)模拟实现三种智能指针

来源:互联网 发布:法医秦明 知乎 编辑:程序博客网 时间:2024/05/18 01:21

在上一篇博客中提到了Auto_ptr(C++智能指针(一)),下面进行模拟实现Auto_ptr
采用类模板实现

#include<iostream>using namespace std;template<class T>class Autoptr{public:    Autoptr(T* ptr = NULL)        :_ptr(ptr)    {}    //Autoptr()        :_ptr(NULL)    //{}    Autoptr(Autoptr<T>& ap)    {        this->_ptr = ap._ptr;        ap._ptr = NULL;    }    Autoptr<T>& operator=(Autoptr<T>& sp)    {        if (this != &sp)        {            delete this->_ptr;            _ptr = sp._ptr;            sp._ptr = NULL;        }        return *this;    }    T* operator->()    {        return _ptr;    }    T operator*()    {        return *_ptr;    }    ~Autoptr()    {        delete _ptr;        _ptr = NULL;    }    void  Reset(T* ptr = 0)    {        if (_ptr != ptr)        {            delete  _ptr;        }        _ptr = ptr;    }protected:    T* _ptr;};void test(){    //int *p1 = new int(10);    //Autoptr<int>ap1(p1);    Autoptr<int> ap1(new int(10));//上面的两行代码可以直接用本行代码代替    cout << *ap1 << endl;    Autoptr<int> ap2(ap1);    cout << *ap2 << endl;    Autoptr<int> ap3(new int(20));    ap3 = ap2;    cout << *ap3 << endl;    //cout << *ap1 << endl;//会使代码出错}int main(){    test();    system("pause");    return 0;}

这里写图片描述
这里写图片描述


//cout << *ap1 << endl;//会使代码出错
这是test函数中的代码,执行这句代码,会使程序崩溃,这是因为ap1已经把它指向的空间交给了ap2去管理,所以ap1已经不具备访问原来自己所指向的空间的权限。所以对它进行解引用是非法的。
所以可以看清auto_ptr的本质是管理权的转移,即ap1将自己所指向的空间交给ap2来管理,析构也是由ap2来完成。


由上面可知auto_ptr有严重缺陷,所以后来有人写了scopedptr,慢慢发展形成了第三方库。
scopedptr ->防拷贝,意思就是不能进行拷贝,简单地说是一种简单粗暴的方式。下面模拟实现scopedptr。采用模板类实现。

template<class T>class scopedptr{public:    scopedptr(T *ptr)        :_ptr(ptr)    {}    T* operator->()    {        return _ptr;    }    T operator*()    {        return *_ptr;    }    ~scopedptr()    {        delete _ptr;        _ptr = NULL;    }protected:    scopedptr<T>& operator=(const scopedptr<T>& s);    scopedptr(scopedptr<T>& ap);private:    T* _ptr;};void test(){    scopedptr<int> s1(new int(10));    //scopedptr<int> s2(s1);//有错误,编译不通过    cout << *s1 << endl;}int main(){    test();    system("pause");    return 0;}

scopedptr中对拷贝构造函数和赋值运算符的重载函数只是进行了声明,并没有去定义这两个函数,而且声明为protected或者是private,这是防止别人在类外对这两个函数进行定义。防止拷贝,所以说scopedptr是一种简单粗暴的方式。


编写程序往往要用到拷贝,这样scopedptr就不能起到相应的作用,所以便有了shared_ptr。
shared_ptr->采用了引用计数,优点是功能强大,但是也有缺点,缺点是过于复杂,而且会引起循环引用。
下面模拟实现shared_ptr

#include<iostream>using namespace std;template<class T>class sharedptr{public:    sharedptr(T* ptr) //构造        :_ptr(ptr), _refcount(new int(1))    {}    sharedptr() //构造        :_ptr(NULL), _refcount(new int(1))    {}    sharedptr(const sharedptr<T>& sp) //拷贝构造        :_ptr(sp._ptr), _refcount(sp._refcount)    {        (*_refcount)++;    }    sharedptr<T>& operator=(const sharedptr<T>& sp) //赋值运算符的重载    {        if (_ptr != sp._ptr)        {            delete _ptr;            delete _refcount;            _ptr = sp._ptr;            _refcount = sp._refcount;            ++(*_refcount);        }        return *this;    }    ~sharedptr() //析构    {        Realease();    }    T& operator*()    {        return *_ptr;    }    T* operator->()    {        return _ptr;    }    T Getrefcount()    {        return *(_refcount);    }    inline void Realease()    {        if (--*_refcount == 0)        {            delete _refcount;            delete _ptr;        }    }    void  Reset(T* ptr ,T* refcount)    {        if (_ptr != ptr)        {            delete  _ptr;            delete _refcount;        }        _ptr = ptr;        _refcount = refcount;    }public:    T* _ptr;    T* _refcount;    //T _refcount;//有缺陷    //int static _refcount;//有缺陷};void test(){    sharedptr<int> s1(new int(10));    //cout << *s1._refcount << endl;    cout << s1.Getrefcount() << endl;    sharedptr<int> s2(s1);    //cout << *s2._refcount << endl;    cout << s2.Getrefcount() << endl;    sharedptr<int> s3(new int(20));    s3 = s1;    //cout << *s3._refcount << endl;    cout << s3.Getrefcount() << endl;}int main(){    test();    //*sharedptr<int> sp;  // 验证Reset    //sp.Reset(new int,new int(1));           //*sp = 10;    //cout << *sp << endl;    //sp.Reset(new int, new int(1));      //*sp = 20;    //cout << *sp << endl;    //sp.Reset();     system("pause");    return 0;}

这里写图片描述

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 牛仔a字裙易变形怎么办 红色皮衣染色了怎么办 羽绒服干了结块怎么办 羽绒服手洗后鸭毛堆在一起怎么办 白色羽绒服发霉了怎么办 早晨起床双脚冷怎么办 黑色棉衣粘毛怎么办 貂皮大衣旧了怎么办 pu皮床头掉皮怎么办 背心领子大怎么办鸡心 羊毛裙子缩水了怎么办 背带裙背带老掉怎么办 背带裙背带坏了怎么办 黑色衣服发红了怎么办 公司拖欠离职员工工资怎么办 windows系统坏了怎么办 背带裙肩带总掉怎么办 四个月宝宝干咳怎么办 4个多月宝宝干咳怎么办 小孩吃饭不嚼怎么办 四个月宝宝积食怎么办 新生儿睡枕头了怎么办 宝宝半夜练翻身怎么办 宝宝牙齿长歪怎么办 婴儿睡觉头歪怎么办 婴儿放在床就哭怎么办 宝宝米粉没吃完怎么办 宝宝吃米粉上火怎么办 幼儿发烧怎么办 两岁 七个月婴儿厌食怎么办 打卤时肉总是沾在一起怎么办 宝宝大便头干硬怎么办 婴儿辅食机的水怎么办 三岁宝宝牙痛怎么办 5岁宝宝牙痛怎么办 6岁儿童脑维缩怎么办 产后奶水多胀痛怎么办 新生儿心脏偏大怎么办 婴儿脸上长虫斑怎么办 婴儿脸上长斑怎么办 婴儿润肤油过敏怎么办