zoukankan      html  css  js  c++  java
  • STL源码剖析-waked_ptr

    目录

    一、提问

    二、 代码实现

    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

  • 相关阅读:
    S3C6410移植uboot2013.01
    linux设备驱动中的并发控制
    明年我多大?(20060119 16:38:41)(新浪)
    冲动&当机立断(20060119 16:58:32)(新浪)
    不能老是雜感,老婆說(20060901 13:14:50)(新浪)
    最近比较烦(20061014 13:14:48)(新浪)
    结婚(20060221 16:31:33)(新浪)
    坐井观天的蛙(20060913 14:19:51)(新浪)
    酒喝大了(20060105 18:41:55)(新浪)
    不可越俎代庖(20060211 21:24:49)(新浪)
  • 原文地址:https://www.cnblogs.com/cnhk19/p/15028816.html
Copyright © 2011-2022 走看看