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;
}

结果如下

posted @ 2016-11-08 08:12  banananana  阅读(3087)  评论(0编辑  收藏  举报