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!\n";
    
    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;
}

結果如下


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM