文档章节

引用计数实现

首席吹牛官
 首席吹牛官
发布于 2015/05/22 12:50
字数 734
阅读 1
收藏 0

在看More Effective C++时就有引用计数,现在自己实现了下。

完成计数的基类

/************************************************
*
*author:周翔
*e-mail:604487178@qq.com
*blog:http://blog.csdn.net/zhx6044
*
*
*************************************************/

#ifndef REFCOUNTER_H
#define REFCOUNTER_H

#include <iostream>

class RefCounter
{
public:
    RefCounter();
    virtual ~RefCounter() = 0;
    void plusOneRef();
    void minusOneRef();
    bool isShared() const;
private:
    int m_refCounter;
};

#endif // REFCOUNTER_H

/************************************************
*
*author:周翔
*e-mail:604487178@qq.com
*blog:http://blog.csdn.net/zhx6044
*
*
*************************************************/

#include "refcounter.h"

RefCounter::RefCounter():m_refCounter(1)
{
}

RefCounter::~RefCounter()
{

}

void RefCounter::plusOneRef()
{
    ++m_refCounter;

}

void RefCounter::minusOneRef()
{
    --m_refCounter;

}

bool RefCounter::isShared() const
{
    return m_refCounter > 1;
}

一个需要实现引用计数的类

/************************************************
*
*author:周翔
*e-mail:604487178@qq.com
*blog:http://blog.csdn.net/zhx6044
*
*
*************************************************/

#ifndef OBJECT_H
#define OBJECT_H

#include <cstring>

#include "refcounter.h"

class Object : public RefCounter
{
    friend Object operator +(const Object& _v1, const Object& _v2);
public:
    Object(const char* _value);
    virtual ~Object();
    Object(const Object& _v);
    const char* className() const;
private:
    char *pd;
};

#endif // OBJECT_H

/************************************************
*
*author:周翔
*e-mail:604487178@qq.com
*blog:http://blog.csdn.net/zhx6044
*
*
*************************************************/

#include "object.h"
#include <iostream>

Object::Object(const char *_value)
{
    pd = new char[strlen(_value) + 1];
    strcpy(pd, _value);
}

Object::~Object()
{
    if (!isShared()) {
        delete[] pd;
    }
}

Object operator +(const Object& _v1, const Object& _v2)
{
    return Object((std::string(_v1.pd) + _v2.pd).data());
}

Object::Object(const Object &_v)
{
    pd = new char[strlen(_v.pd) + 1];
    strcpy(pd,_v.pd);
}

const char* Object::className() const
{
    return pd;
}

一个实现引用判断的外裹类模板,封装了逻辑

/************************************************
*
*author:周翔
*e-mail:604487178@qq.com
*blog:http://blog.csdn.net/zhx6044
*
*
*************************************************/

#ifndef REFCOUNTERWAPPER_H
#define REFCOUNTERWAPPER_H

#include <iostream>


template <typename T>
class RefCounterWapper
{
public:
    RefCounterWapper(T *p);
    ~RefCounterWapper();
    RefCounterWapper(const T& _v);
    RefCounterWapper(const RefCounterWapper &_v);
    RefCounterWapper& operator =(const RefCounterWapper& _v);
    const T* operator ->() const;
    const T& operator *() const;
    T* operator ->();
    T& operator *();
private:
    T *pd;
};

template <typename T>
RefCounterWapper<T>::RefCounterWapper(T *p):pd(p)
{

}

template <typename T>
RefCounterWapper<T>::~RefCounterWapper()
{
    if (!pd->isShared()) {
        delete pd;
    } else {
        pd->minusOneRef();
    }

}

template <typename T>
RefCounterWapper<T>::RefCounterWapper(const T &_v)
{
    pd = new T(_v);
}

template <typename T>
RefCounterWapper<T>::RefCounterWapper(const RefCounterWapper &_v)
{
    pd = _v.pd;
    pd->plusOneRef();
}

template <typename T>
RefCounterWapper<T>& RefCounterWapper<T>::operator =(const RefCounterWapper& _v)
{
    if (this == &_v) return *this;
    pd->minusOneRef();
    if (!pd->isShared()) {
        delete pd;
    }
    pd = _v.pd;
    pd->plusOneRef();
    return *this;
}

template <typename T>
const T* RefCounterWapper<T>::operator ->() const
{
    return  pd;
}

template <typename T>
const T& RefCounterWapper<T>::operator *() const
{
    return *pd;
}

template <typename T>
T* RefCounterWapper<T>::operator ->()
{
    return  pd;
}

template <typename T>
T& RefCounterWapper<T>::operator *()
{
    return *pd;
}

#endif // REFCOUNTERWAPPER_H

供外部使用的具有计数功能的类

/************************************************
*
*author:周翔
*e-mail:604487178@qq.com
*blog:http://blog.csdn.net/zhx6044
*
*
*************************************************/

#ifndef REFCOUNTEROBJECT_H
#define REFCOUNTEROBJECT_H

#include "refcounterwapper.h"
#include "object.h"




class RefCounterObject
{
    friend RefCounterObject operator +(const RefCounterObject& _v1, const RefCounterObject& _v2);
public:
    RefCounterObject(const char* _v = "Object");
    virtual ~RefCounterObject();
    const char* className() const;
private:
    RefCounterObject(const Object& _v);
    RefCounterWapper<Object> pd;
};


RefCounterObject::RefCounterObject(const char *_v):pd(new Object(_v))
{

}


RefCounterObject::~RefCounterObject()
{

}

RefCounterObject operator +(const RefCounterObject& _v1, const RefCounterObject& _v2)
{
    return RefCounterObject((*_v1.pd) + (*_v2.pd));
}

RefCounterObject::RefCounterObject(const Object &_v):pd(_v)
{

}

const char* RefCounterObject::className() const
{
    return pd->className();
}

#endif // REFCOUNTEROBJECT_H

测试代码

#include <iostream>
#include "refcounterobject.h"

using namespace std;

int main()
{
    RefCounterObject v("zhou love cc");
    cout << v.className() << endl;
    RefCounterObject v2 = v;
    cout << v2.className() << endl;
    RefCounterObject v3(v2);
    cout << v3.className() << endl;
    RefCounterObject v4;
    cout << v4.className() << endl;
    v4 = v3;
    cout << v4.className() << endl;

    RefCounterObject v5 = v4 + v2;
    cout << v5.className() << endl;


}

5个对象共享了2个Object,它们保存的字符串的值,分别位zhou love cc和zhou love cczhou love cc。

用Valgrind分析了内存,没有内存泄漏


分析Object的析构函数被调用几次

5个对象有两个Object对象,调用析构2次,

还有各一次是

RefCounterObject v4;
    cout << v4.className() << endl;
    v4 = v3;//析构v4开始的Object
    cout << v4.className() << endl;

    RefCounterObject v5 = v4 + v2;//+操作底层产生一个局部的Object
    cout << v5.className() << endl;



共享的是RefCounterWapper中pd这个指针指向的对象。


这几个类的关系如图






本文转载自:http://blog.csdn.net/zhx6044/article/details/9152451

首席吹牛官
粉丝 9
博文 368
码字总数 191938
作品 0
闵行
程序员
私信 提问
Android上C++对象的自动回收机制分析

1. 背景 C++没有像Java那样的内建的对象自动回收机制,new创建的对象没有delete,会一直存在于内存中。对象已经不再使用,但是如果忘记 delete,会造成内存资源的泄露。在实际开发过程中,分...

阿酷
2011/12/26
1K
0
探寻Objective-C引用计数本质

本文涉及到的CPU架构为arm64,其它架构大同小异。 源码来自苹果开源-runtime。 Objective-C中采用引用计数机制来管理内存,在MRC时代,需要我们手动和,在苹果引入ARC后大部分时间我们不用再...

莫云溪
2018/05/26
0
0
Android系统的智能指针(轻量级指针、强指针和弱指针)的实现原理分析【转】

Android系统的运行时库层代码是用C++来编写的,用C++ 来写代码最容易出错的地方就是指针了,一旦使用不当,轻则造成内存泄漏,重则造成系统崩溃。不过系统为我们提供了智能指针,避免出现上述...

yooooooo
2018/08/20
0
0
Android系统的智能指针(轻量级指针、强指针和弱指针)的实现原理分析

Android系统的运行时库层代码是用C++来编写的,用C++来写代码最容易出错的地方就是指针了,一旦使用不当,轻则造成内存泄漏,重则造成系统崩溃。不过系统为我们提供了智能指针,避免出现上述...

鉴客
2011/10/17
1K
0
objective-c启用ARC时的内存管理

PDF版下载:http://download.csdn.net/detail/cuibo1123/7443125 在objective-c中,内存的引用计数一直是一个让人比较头疼的问题。尤其是当引用计数涉及到arc、blocks等等的时候。似乎ARC的出...

cuibo1123
2014/06/04
0
0

没有更多内容

加载失败,请刷新页面

加载更多

OSChina 周日乱弹 —— 我,小小编辑,食人族酋长

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @宇辰OSC :分享娃娃的单曲《飘洋过海来看你》: #今日歌曲推荐# 《飘洋过海来看你》- 娃娃 手机党少年们想听歌,请使劲儿戳(这里) @宇辰OSC...

小小编辑
39分钟前
84
5
spring cloud

一、从面试题入手 1.1、什么事微服务 1.2、微服务之间如何独立通讯的 1.3、springCloud和Dubbo有哪些区别 1.通信机制:DUbbo基于RPC远程过程调用;微服务cloud基于http restFUL API 1.4、spr...

榴莲黑芝麻糊
今天
2
0
Executor线程池原理与源码解读

线程池为线程生命周期的开销和资源不足问题提供了解决方 案。通过对多个任务重用线程,线程创建的开销被分摊到了多个任务上。 线程实现方式 Thread、Runnable、Callable //实现Runnable接口的...

小强的进阶之路
昨天
6
0
maven 环境隔离

解决问题 即 在 resource 文件夹下面 ,新增对应的资源配置文件夹,对应 开发,测试,生产的不同的配置内容 <resources> <resource> <directory>src/main/resources.${deplo......

之渊
昨天
8
0
详解箭头函数和普通函数的区别以及箭头函数的注意事项、不适用场景

箭头函数是ES6的API,相信很多人都知道,因为其语法上相对于普通函数更简洁,深受大家的喜爱。就是这种我们日常开发中一直在使用的API,大部分同学却对它的了解程度还是不够深... 普通函数和...

OBKoro1
昨天
7
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部