第28课 再论智能指针(下)

1. SharedPointer的设计

(1)使用类模板,通过计数机制标识堆内存

(2)堆内存被指向时,(*refCount)++

(3)指针被置空时:(*refCount)—

(4)当*refCount == 0时,释放堆内存

2. 计数机制原理剖析

第28课 再论智能指针(下) 

3. SharedPointer类的声明

template <typename T>
class SharedPointer : public Pointer<T>
{
protected:
    int* m_refCount; //计数机制成员
public:
    SharedPointer(T* p = NULL);
    SharedPointer(const SharedPointer<T>& obj);

    SharedPointer<T>& operator=(const SharedPointer<T>& obj);

    void clear(); //将当前指针置为空

    //由于SharedPointer支持多个对象同时指向一片堆空间
    //因此必须支持比较操作!
    bool operator==(const SharedPointer<T>& obj);
    bool operator!=(const SharedPointer<T>& obj);

    ~SharedPointer();
};

4. 智能指针使用军规

(1)只能用来指向堆空间中的单个对象(变量)

(2)不同类型的智能指针对象不能混合使用

(3)不要使用delete释放智能指针指向的堆空间

【编程实验】SharedPointer智能指针的实现

//Pointer.h

#ifndef _POINTER_H_
#define _POINTER_H_

#include "Object.h"

namespace DTLib {

template <typename T>
class Pointer : public Object //Object是析构函数本身是纯虚函数!
{
protected:
    T* m_pointer;
public:
    Pointer(T* p = NULL)
    {
        m_pointer = p;
    }

    T* operator->()
    {
        return m_pointer;
    }

    T& operator*()
    {
        return *m_pointer;
    }

    const T* operator->() const
    {
        return m_pointer;
    }

    const T& operator*() const
    {
        return *m_pointer;
    }

    bool isNull() const
    {
        return (m_pointer == NULL);
    }

    T* get() const
    {
        return m_pointer;
    }
};

}

#endif // _POINTER_H_

//SharedPointer.h

#ifndef _SHAREDPOINTER_H_
#define _SHAREDPOINTER_H_

#include "Pointer.h"
#include "exception.h"
#include <cstdlib>

namespace DTLib
{
template <typename T>
class SharedPointer : public Pointer <T>
{
protected:
    int * m_ref;

    void assign(const SharedPointer<T> &obj)
    {    //复制
        this->m_ref = obj.m_ref;
        this->m_pointer = obj.m_pointer; //指向后者的堆内存

        if (this->m_ref)
        {       //如果指向了合法的指针变量
            (*this->m_ref)++; //计数加1
        }
    }
public:
    SharedPointer(T *p = NULL) : m_ref(NULL)
    {
        if (p)
        {    //堆空间中申请4个字节的空间
//
注意此处不用new,因为int是基本类型不是Object的子类,也就无法享受Object类中重载new的好处,即new int失败时,由于编译器处理方式不同,仍可能是NULL或抛异常。为了统一处理,用malloc
            this->m_ref = static_cast<int*>(malloc(sizeof(int)));

            if (this->m_ref)
            {
                *(this->m_ref) = 1;    //初始化1 ,说明p的堆空间已经有一个sharedpointer指针指向了
                this->m_pointer = p;
            }
            else
            {    //若malloc不成功,抛出异常
                THROW_EXCEPTION(NotEnoughMemoryException, "No memory to create SharedPointer object ... ");
            }
        }
    }

    SharedPointer(const SharedPointer<T> &obj) : Pointer<T>(NULL)
    { //拷贝构造函数
        assign(obj);
    }

    SharedPointer<T> &operator =(const SharedPointer<T> &obj)
    {
        if (this != &obj)
        {    //避免自赋值
            clear(); //  如果当前的sharepointer指针已经指向 另外一片堆空间,
            //应该先置空当前指针,不让它指向任何堆空间
            assign(obj);
        }

        return *this;
    }

    void clear()
    { //置空函数
        T *toDel = this->m_pointer;
        int *ref = this->m_ref;

        this->m_pointer = NULL;
        this->m_ref = NULL;

        if (ref)
        { //如果ref不为空指针
            (*ref)--;//释放一个指针减1

            if (*ref == 0) //若堆空间没有对应的指针指向
            {
                free(ref);

                delete toDel;
            }
        }
    }
    //由于SharedPointer支持多个对象同时指向一片堆空间。因此必须支持比较操作!
    bool operator==(const SharedPointer<T>& obj)
    {
        return (this->m_pointer == obj.m_pointer);
    }

    bool operator!=(const SharedPointer<T>& obj)
    {
        return (this->m_pointer != obj.m_pointer);
    }

    ~SharedPointer()
    {
        clear();
    }
};

}
#endif // _SHAREDPOINTER_H_

//main.cpp

#include <iostream>
#include "SharedPointer.h"

using namespace std;
using namespace DTLib;

class Test : public Object
{
public:
    int value;

    Test(): value(0)
    {
        cout << "Test()" << endl;
    }

    ~Test()
    {
        cout <<"~Test()" << endl;
    }
};

int main()
{
    //const SharedPointer<Test> sp0 = new Test();
    SharedPointer<Test> sp0 = new Test();
    SharedPointer<Test> sp1 = sp0;
    SharedPointer<Test> sp2 = NULL;

    sp2 = sp1;

    sp0->value = 100;

    cout << sp0->value << endl;
    cout << sp1->value << endl;
    cout << sp2->value << endl;

    //sp1.clear();

    cout << (sp0==sp1) << endl;

    return 0;
}
/*输出结果
Test()
100
100
100
1
~Test()
*/

5. 小结

(1)SharedPointer最大程度的模拟了原生指针的行为

(2)计数机制确保多个智能指针合法的指向同一片堆空间

(3)智能指针只能用于指向堆空间中的内存

(4)不同类型的智能指针不要混合使用

(5)堆对象的生命周期由智能指针进行管理

原文链接: https://www.cnblogs.com/5iedu/p/7077025.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍;

也有高质量的技术群,里面有嵌入式、搜广推等BAT大佬

    第28课 再论智能指针(下)

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/393231

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
adminadmin
0 0
第6章 静态路由和动态路由(3)_RIP动态路由协议
上一篇 2023年4月3日 下午3:08
第27课 再论智能指针(上)
下一篇 2023年4月3日 下午3:08

相关推荐

  • c++设置左对齐 2023年2月8日
  • rust与C++中类型别名比较 2023年3月2日
  • 使用UTF8-CPP转换unicode编码 附录:UTF8和UTF16和UTF32和Unicode编码 2023年2月13日
  • 2-3 C++复合类型 2023年2月12日
  • 字符串按规则排序算法_根据一定规则重置排序算法 2023年4月26日
  • C++11 —— 获取 tuple 参数列表中指定数据类型的索引位置 2023年3月1日
  • 12.9K

    我是职场上失宠的妃子

  • C++性能真的不如C吗?

    7.2K
  • 大话数据结构 高清PDF

    6.7K
  • string底层实现之SSO

    6.3K
  • 千百撸

    4.4K
  • GDB调试-从入门实践到原理

    3.7K
  • 什么是COM

    3.7K
  • std::string底层实现之COW(Copy-On-Write)

    3.6K
  • 智能指针-使用、避坑和实现

    3.6K
  • 彻底搞通TCP send和recv原理

    3.4K

深圳SEO优化公司惠州模板推广同乐seo坪地阿里店铺运营罗湖网站制作西乡网站seo优化爱联网站改版布吉网站推广方案大芬seo排名大浪网站建设南山网站优化推广双龙关键词按天计费大芬网站建设设计沙井网络推广盐田至尊标王民治设计网站布吉网站定制民治网站优化按天扣费塘坑网站设计宝安百度爱采购塘坑网站优化推广爱联至尊标王大浪如何制作网站观澜SEO按效果付费塘坑模板制作大运百搜词包永湖网站排名优化石岩百度竞价双龙网页制作大鹏百姓网标王民治网站定制歼20紧急升空逼退外机英媒称团队夜以继日筹划王妃复出草木蔓发 春山在望成都发生巨响 当地回应60岁老人炒菠菜未焯水致肾病恶化男子涉嫌走私被判11年却一天牢没坐劳斯莱斯右转逼停直行车网传落水者说“没让你救”系谣言广东通报13岁男孩性侵女童不予立案贵州小伙回应在美国卖三蹦子火了淀粉肠小王子日销售额涨超10倍有个姐真把千机伞做出来了近3万元金手镯仅含足金十克呼北高速交通事故已致14人死亡杨洋拄拐现身医院国产伟哥去年销售近13亿男子给前妻转账 现任妻子起诉要回新基金只募集到26元还是员工自购男孩疑遭霸凌 家长讨说法被踢出群充个话费竟沦为间接洗钱工具新的一天从800个哈欠开始单亲妈妈陷入热恋 14岁儿子报警#春分立蛋大挑战#中国投资客涌入日本东京买房两大学生合买彩票中奖一人不认账新加坡主帅:唯一目标击败中国队月嫂回应掌掴婴儿是在赶虫子19岁小伙救下5人后溺亡 多方发声清明节放假3天调休1天张家界的山上“长”满了韩国人?开封王婆为何火了主播靠辱骂母亲走红被批捕封号代拍被何赛飞拿着魔杖追着打阿根廷将发行1万与2万面值的纸币库克现身上海为江西彩礼“减负”的“试婚人”因自嘲式简历走红的教授更新简介殡仪馆花卉高于市场价3倍还重复用网友称在豆瓣酱里吃出老鼠头315晚会后胖东来又人满为患了网友建议重庆地铁不准乘客携带菜筐特朗普谈“凯特王妃P图照”罗斯否认插足凯特王妃婚姻青海通报栏杆断裂小学生跌落住进ICU恒大被罚41.75亿到底怎么缴湖南一县政协主席疑涉刑案被控制茶百道就改标签日期致歉王树国3次鞠躬告别西交大师生张立群任西安交通大学校长杨倩无缘巴黎奥运

深圳SEO优化公司 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化