简介
引用计数就是对一个对象记录其被引用的次数,其的引用计数可加可减,那什么时候加什么时候减呢?所以引用计数的重点在于在哪里加,在哪里减;
加:
减:
实现
//
// 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;
}
结果如下