目录

一、提问

二、 代码实现

2.1 mweak_ptr的具体实现

2.2 测试用例
一、提问

weak_ptr为什么会存在?shared_ptr不是已经有了引用计数吗?具体原因详见模拟实现boost库中的shared_ptr,简单来说就是为了解决循环引用(交叉引用)的问题。

weak_ptr是为了配合shared_ptr而引入的一种智能指针,更像是shared_ptr的一个助手而不是智能指针(不具备普通指针的行为operator*和operator->),最大的作用在于协助shared_ptr工作,像旁观者那样观测资源的使用情况!weak_ptr是与shared_ptr协同工作的:获取资源的观测权,并没有共享资源!而构造weak_ptr不会引起引用计数的变化。
二、 代码实现
2.1 mweak_ptr的具体实现

为了和boost库中的weak_ptr区分,我在命名时加上了m(含义是my)。mshared_ptr已在文首的模拟实现boost库中的shared_ptr讨论过了,故而不在赘述。先将代码粘贴如下。

mshared_ptr部分:

    #include<iostream>
    using namespace std;
    #include<map>
     
    template<typename T>
    class mweak_ptr;
     
    template<typename T>
    class mshared_ptr
    {
    public:
        mshared_ptr(T *ptr = NULL);        //构造方法
        ~mshared_ptr();        //析构方法
        mshared_ptr(mshared_ptr<T> &src);        //拷贝构造
        mshared_ptr& operator = (mshared_ptr<T> &src);        //赋值运算符重载
        T& operator*();        //解引用运算符重载
        T* operator->();    //成员运算符重载
    private:
        T *_ptr;
        static map<T*, int> _map;        //静态数据成员需要在类外进行初始化
        friend class mweak_ptr<T>;
    };
     
    template<typename T>
    map<T*, int> mshared_ptr<T>::_map;
     
    template<typename T>
    mshared_ptr<T>::mshared_ptr(T *ptr)        //构造方法
    {
        cout << "mshared_ptr的构造方法正被调用!" << endl;
        _ptr = ptr;
        _map.insert(make_pair(_ptr, 1));
    }
     
    template<typename T>
    mshared_ptr<T>::~mshared_ptr()        //析构方法
    {
        cout << "mshared_ptr的析构方法正被调用!" << endl;
        if (--_map[_ptr] <= 0 && NULL != _ptr)
        {
            delete _ptr;
            _ptr = NULL;
            _map.erase(_ptr);
        }
    }
     
    template<typename T>
    mshared_ptr<T>::mshared_ptr(mshared_ptr<T> &src)    //拷贝构造
    {
        cout << "mshared_ptr的拷贝构造方法正被调用!" << endl;
        _ptr = src._ptr;
        _map[_ptr]++;
    }
     
    template<typename T>
    mshared_ptr<T>& mshared_ptr<T>::operator=(mshared_ptr<T> &src)        //赋值运算符重载
    {
        if (_ptr == src._ptr)
        {
            return *this;
        }
     
        if (--_map[_ptr] <= 0 && NULL != _ptr)
        {
            delete _ptr;
            _ptr = NULL;
            _map.erase(_ptr);
        }
     
        _ptr = src._ptr;
        _map[_ptr]++;
        return *this;
    }
     
    template<typename T>
    T& mshared_ptr<T>::operator*()        //解引用运算符重载
    {
        return *_ptr;
    }
     
    template<typename T>
    T* mshared_ptr<T>::operator->()        //成员运算符重载
    {
        return _ptr;
    }

mweak_ptr部分

    template<typename T>
    class mweak_ptr
    {
    public:
        mweak_ptr(){}    //需要提供一个默认的构造方法
        mweak_ptr(mshared_ptr<T> &src);        //构造方法
        mshared_ptr<T> lock();
    private:
        mshared_ptr<T> *_ptr;
    };
     
    template<typename T>
    mweak_ptr<T>::mweak_ptr(mshared_ptr<T> &src)    //使用强指针进行构造
    {
        _ptr = &src;
    }
     
    template<typename T>
    mshared_ptr<T> mweak_ptr<T>::lock()    //返回一个可用的强指针
    {
        int count = _ptr->_map[_ptr->_ptr];
        if (count > 0)        //从shared_ptr获得一个可用的shared_ptr对象。从而操作资源
        {
            return *_ptr;
        }
        else
        {
            return NULL;
        }
    }
     
    void test(mweak_ptr<int> mweak_p)
    {
        cout << *mweak_p.lock() << endl;
    }

2.2 测试用例

    class B;
    class A
    {
    public:
        mweak_ptr<B>_ptr_B;        //类内存放的是弱指针,将在合适的时间转变成强指针!
    };
    class B
    {
    public:
        mweak_ptr<A>_ptr_A;
    };
     
    int main()
    {
        mshared_ptr<A>ptr_A(new A);
        mshared_ptr<B>ptr_B(new B);
        ptr_A->_ptr_B = ptr_B;
        ptr_B->_ptr_A = ptr_A;
        return 0;
    }

图1 VS2017下验证结果

从图中可以看到,构造方法和析构方法的执行次数是相同的,故而引用计数没有被占用,申请的内存成功被释放了。
————————————————
版权声明:本文为CSDN博主「楚楚可薇」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_41822235/article/details/82936615

STL源码剖析-waked_ptr的更多相关文章

  1. STL"源码"剖析-重点知识总结

    STL是C++重要的组件之一,大学时看过<STL源码剖析>这本书,这几天复习了一下,总结出以下LZ认为比较重要的知识点,内容有点略多 :) 1.STL概述 STL提供六大组件,彼此可以组合 ...

  2. 【转载】STL"源码"剖析-重点知识总结

    原文:STL"源码"剖析-重点知识总结 STL是C++重要的组件之一,大学时看过<STL源码剖析>这本书,这几天复习了一下,总结出以下LZ认为比较重要的知识点,内容有点 ...

  3. (原创滴~)STL源码剖析读书总结1——GP和内存管理

    读完侯捷先生的<STL源码剖析>,感觉真如他本人所说的"庖丁解牛,恢恢乎游刃有余",STL底层的实现一览无余,给人一种自己的C++水平又提升了一个level的幻觉,呵呵 ...

  4. 《STL源码剖析》环境配置

    首先,去侯捷网站下载相关文档:http://jjhou.boolan.com/jjwbooks-tass.htm. 这本书采用的是Cygnus C++ 2.91 for windows.下载地址:ht ...

  5. STL源码剖析读书笔记之vector

    STL源码剖析读书笔记之vector 1.vector概述 vector是一种序列式容器,我的理解是vector就像数组.但是数组有一个很大的问题就是当我们分配 一个一定大小的数组的时候,起初也许我们 ...

  6. STL源码剖析 迭代器(iterator)概念与编程技法(三)

    1 STL迭代器原理 1.1  迭代器(iterator)是一中检查容器内元素并遍历元素的数据类型,STL设计的精髓在于,把容器(Containers)和算法(Algorithms)分开,而迭代器(i ...

  7. STL"源码"剖析

    STL"源码"剖析-重点知识总结   STL是C++重要的组件之一,大学时看过<STL源码剖析>这本书,这几天复习了一下,总结出以下LZ认为比较重要的知识点,内容有点略 ...

  8. 《STL源码剖析》相关面试题总结

    原文链接:http://www.cnblogs.com/raichen/p/5817158.html 一.STL简介 STL提供六大组件,彼此可以组合套用: 容器容器就是各种数据结构,我就不多说,看看 ...

  9. STL源码剖析之序列式容器

    最近由于找工作需要,准备深入学习一下STL源码,我看的是侯捷所著的<STL源码剖析>.之所以看这本书主要是由于我过去曾经接触过一些台湾人,我一直觉得台湾人非常不错(这里不涉及任何政治,仅限 ...

随机推荐

  1. DotNetty实现WebSocket的简单使用

    工作中项目是物联网项目的,管理平台又是bs架构. 如果用 Socket 的话,Web 端还需要转发,就全部统一采用了 WebSocket . DotNet 平台上的 WebSocket 实现有很多种, ...

  2. [省选联考 2021 A/B 卷] 宝石

    大概是一眼看出来是这个给定序列在树上序列上按顺序跑最大匹配. 然后考虑维护向上和向下的链的值. 大概的做法是用倍增维护,考虑\(f_{u,i}\)是\(c_u\)在序列里的位置向后匹配\(2^i\)位 ...

  3. Topcoder 15405 - PrettyLiar(可删除背包+前缀和优化 dp)

    题面传送门 题意: 给出两个长度为 \(n\) 的数组 \(a,b\) 和一个整数 \(s\). 你可以任意重排数组 \(a,b\),总共 \((n!)^2\) 种方案. 现在又两个人 A,B 来玩游 ...

  4. Atcoder Grand Contest 033 D - Complexity(dp)

    Atcoder 题面传送门 & 洛谷题面传送门 首先 \(n^5\) 的暴力非常容易想,设 \(dp_{a,b,c,d}\) 表示以 \((a,b)\) 为左上角,\((c,d)\) 为右下角 ...

  5. UOJ 422 - 【集训队作业2018】小Z的礼物(Min-Max 容斥+轮廓线 dp)

    题面传送门 本来说要找道轮廓线 \(dp\) 的题目刷刷来着的?然后就找到了这道题. 然鹅这个题给我最大的启发反而不在轮廓线 \(dp\),而在于让我新学会了一个玩意儿叫做 Min-Max 容斥. M ...

  6. 学军中学csp-noip2020模拟5

    Problem List(其实这几场全是附中出的) 这场比赛的题目相当有价值,特别是前两题,相当的巧妙. A.路径二进制 数据范围这么小,当然是搜索. \(30pts:\)大力搜索出奇迹,最后统计答案 ...

  7. dokuwiki使用随笔

    1. 在dokuwiki上安装MataJax插件后: a. $....$:之间书写数学公式;如完全平方公式:$a^2+b^2+2ab$,该公式将与当前行文字处于同一行; b. $$ .... $$ 之 ...

  8. requests+bs4爬取豌豆荚排行榜及下载排行榜app

    爬取排行榜应用信息 爬取豌豆荚排行榜app信息 - app_detail_url - 应用详情页url - app_image_url - 应用图片url - app_name - 应用名称 - ap ...

  9. Phoenix二级索引

    Phoenix Hbase适合存储大量的对关系运算要求低的NOSQL数据,受Hbase 设计上的限制不能直接使用原生的API执行在关系数据库中普遍使用的条件判断和聚合等操作.Hbase很优秀,一些团队 ...

  10. List 去重的 6 种方法,这个方法最完美!

    在日常的业务开发中,偶尔会遇到需要将 List 集合中的重复数据去除掉的场景.这个时候可能有同学会问:为什么不直接使用 Set 或者 LinkedHashSet 呢?这样不就没有重复数据的问题了嘛? ...