簡介
引用計數就是對一個對象記錄其被引用的次數,其的引用計數可加可減,那什么時候加什么時候減呢?所以引用計數的重點在於在哪里加,在哪里減;
加:
減:
實現
//
// 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;
}
結果如下