zoukankan      html  css  js  c++  java
  • C++引用计数

    简介

    引用计数就是对一个对象记录其被引用的次数,其的引用计数可加可减,那什么时候加什么时候减呢?所以引用计数的重点在于在哪里加,在哪里减;

    加:

    减:

    实现

    //
    //  Ref.hpp
    //  Ref
    //
    //  Created by George on 16/11/6.
    //  Copyright © 2016年 George. All rights reserved.
    //
    
    #ifndef Ref_hpp
    #define Ref_hpp
    
    #include <iostream>
    #include <string>
    
    template <typename T>
    class RefPtr;
    
    template <typename T>
    class Ref {
    private:
        Ref(T *ptr);
        ~Ref();
        
        friend class RefPtr<T>; //定义指针管理类为友元,因为管理类需要直接操作指针类
    
        /**
         *  增加引用计数
         */
        void ref();
        
        /**
         *  减少引用计数
         *
         *  @param count <#count description#>
         */
        void unref();
        
        /**
         *  返回引用计数的个数
         *
         *  @return <#return value description#>
         */
        int getCount();
        
    private:
        int count; //引用计数
        T *p; //基础对象指针
    };
    
    template <typename T>
    Ref<T>::Ref(T *ptr) : p(ptr), count(1) {
         
    }
    
    template <typename T>
    Ref<T>::~Ref() {
    //    count--;
    //    if (count <= 0) {
    //        count = 0;
    //        delete p;
    //    }
        delete p;
    }
    
    template <typename T>
    void Ref<T>::ref() {
        count++;
    }
    
    template <typename T>
    void Ref<T>::unref() {
        count--;
        if (count < 0) {
            count = 0;
        }
    }
    
    template <typename T>
    int Ref<T>::getCount() {
        return count;
    }
    
    
    template <typename T>
    class RefPtr {
    public:
        RefPtr(T *ptr);
        RefPtr(const RefPtr<T>&);
        ~RefPtr();
        
        RefPtr& operator=(const RefPtr<T>&);
        T & operator*();
        T * operator->();
        
        inline std::string getTag() { return _tag; };
        void setTag(const std::string value) { _tag = value; };
        
        inline int getRefCount() { return ref->getCount(); }
        
    private:
        Ref<T> *ref;
        std::string _tag;
    };
    
    
    /**
     *  构造函数
     */
    template <typename T>
    RefPtr<T>::RefPtr(T *ptr) : ref(new Ref<T>(ptr)), _tag("") {
        
    }
    
    /**
     *  构造函数,不需要对参数进行计数操作
     */
    template <typename T>
    RefPtr<T>::RefPtr(const RefPtr<T> & nref) {
        ref = nref.ref;
        ref->ref();
        _tag = "";
    }
    
    /**
     *  销毁函数
     */
    template <typename T>
    RefPtr<T>::~RefPtr() {
        ref->unref();
        if (ref->getCount() <= 0) {
            delete ref;
        }
        std::cout << this->getTag() << " leave " << ref->getCount() << "次" << std::endl;
    }
    
    /**
     *  重载操作符=
     *  左值引用计数减一,右值引用计数加一
     *
     *  @param rhs <#rhs description#>
     *
     *  @return <#return value description#>
     */
    template <typename T>
    RefPtr<T> & RefPtr<T>::operator=(const RefPtr<T>& rhs) {
        rhs->ref->ref();
        ref->unref();
        
        if (ref->getCount() <= 0) {
            delete ref;
        }
        
        ref = rhs->ref;
        
        return *this;
    }
    
    /**
     *  重载操作符*
     *
     *  @return <#return value description#>
     */
    template <typename T>
    T & RefPtr<T>::operator*() {
        return *(ref->p);
    }
    
    /**
     *  重载->操作符
     *
     *  @return <#return value description#>
     */
    template <typename T>
    T * RefPtr<T>::operator->() {
        return ref->p;
    }
    
    
    #endif /* Ref_hpp */
    
    

    其中Ref是引用,而RefPtr是对Ref进行操作的封装,在什么时候加减;

    测试

    //
    //  main.cpp
    //  Ref
    //
    //  Created by George on 16/11/6.
    //  Copyright © 2016年 George. All rights reserved.
    //
    
    #include <iostream>
    #include "Ref.hpp"
    
    int main(int argc, const char * argv[]) {
        // insert code here...
        std::cout << "Hello, World!
    ";
        
        int *num = new int(2);
        {
            RefPtr<int> ptr(num);
            {
                ptr.setTag("Ptr1");
                RefPtr<int> ptr2(ptr);
                {
                    ptr2.setTag("Ptr2");
                    
                    RefPtr<int> ptr3 = ptr2;
                    ptr3.setTag("Ptr3");
                    {
                        int *nnum = new int(4);
                        RefPtr<int> ptr4(nnum);
                        ptr4.setTag("Ptr4");
                        
                        std::cout << "ptr:" << *ptr << std::endl;
                        
                        *ptr = 20;
                        
                        std::cout << "ptr3:" << *ptr3 << std::endl;
                        
                        std::cout << "ptr1 have " << ptr.getRefCount() << "次" << std::endl;
                        std::cout << "ptr2 have " << ptr2.getRefCount() << "次" << std::endl;
                        std::cout << "ptr3 have " << ptr3.getRefCount() << "次" << std::endl;
                        std::cout << "ptr4 have " << ptr4.getRefCount() << "次" << std::endl;
                    }
                }
            }
        }
        
        return 0;
    }
    
    

    结果如下

  • 相关阅读:
    C# 执行bat文件 PHP
    windows服务操作 sc批处理 PHP
    HTML 彩虹 PHP
    C# 简易日志记录类 PHP
    C# 读写INI文件 PHP
    .NET Framework PHP
    序列号备忘 PHP
    获取浏览器版本信息
    数据库中Image字段存储读取数据
    [转]装机推荐 5000元铸造最强游戏平台
  • 原文地址:https://www.cnblogs.com/George1994/p/6041398.html
Copyright © 2011-2022 走看看