使用过OC的都知道,OC的引用计数机制用起来还比较方便。于是就仿照OC的形式搞了个C++引用计数。

支持多重自动释放池,每次autorelease都会放到栈顶的自动释放池中。

自动释放池也可以像变量一样有生命周期,在退出block时自动销毁池,并且对池中每个对象调用release.

使用大概如下:

int main(int argc, char * argv[])
{
USING_NAMESPACE_BASE
using namespace std; Data *d = new Data();
d->Autorelease(); {
autorelease_newpool
Data *d = new Data();
d->Autorelease();
{
autorelease_newpool
Data *d = new Data();
d->Autorelease();
}
} Data *d1 = new Data();
d1->Autorelease(); return ;
}

Github:【点击】

概述:

*  - AutoreleasePool 自动释放池类

*  - AutoreleasePoolLifecycleManager 池生命周期类,用于程序块内的池入栈和出栈控制

*  - AutoreleasePoolMarager 池管理器,内部使用栈式结构管理池

*  - RefObject 引用计数基类,提供引用计数的支持

关系梳理:

- 继承自RefObject的类具有,引用计数功能。当调用RefObject的autorelease时,其会通过AutoreleasePoolMarager获得栈顶的AutoreleasePool对象,然后将自己放入pool中。

- AutoreleasePoolMarager是单例,其内部使用栈式结构保存了一个或多个AutoreleasePool对象,供其他对象调用入栈新pool或者出栈销毁pool

- AutoreleasePool管理池中的对象,在pool销毁时会将所有池中RefObject对象release一遍

- AutoreleasePoolLifecycleManager作用就是在构造函数中入栈新pool,在析构函数中出栈pool

RefObject

class RefObject{
public:
/*
* 引用计数加一
* 注意:
* - 只有对堆对象才能生效,栈对象不要使用
*/
void Retain() { assert(m_refcount>); ++m_refcount; } /*
* 引用计数减一
* 注意:
* - 只有对堆对象才能生效,栈对象不要使用
*/
void Release() { if (--m_refcount<=) delete this; } /*
* 自动引用计数减一
* 注意:
* - 只有对堆对象才能生效,栈对象不要使用
*/
void Autorelease() { AutoreleasePoolMarager::GetInstance()->PeekTop()->AddRefObject(this); } /*
* 获得引用计数
* 注意:
* - 只有对堆对象才能生效,栈对象不要使用
*/
int GetRefCount() { return m_refcount; } protected:
RefObject():m_refcount() { }
virtual ~RefObject() { } private:
int m_refcount;
};

AutoreleasePool

class AutoreleasePool {
public:
AutoreleasePool();
~AutoreleasePool(); /*
* 添加对象到自动释放池中
* 说明:
* - 此对象必须为RefObject的子类
*/
void AddRefObject(RefObject *refobject); /*
* 对池中所有对象调用一次Release方法
* 说明:
* - 此方法一般不要手动调用,在析构中会自动调用
* - 调用顺序为,先进的先调用(类似队列结构)
*/
void ReleaseAll(); private:
std::vector<RefObject*> m_refobjects;
};

AutoreleasePoolMarager

class AutoreleasePoolMarager {
public:
static AutoreleasePoolMarager* GetInstance();
static void DestroyInstance(); /*
* 创建一个新的自动释放池,并且入栈
*/
void PushNew(); /*
* 将栈顶的自动释放池出栈,并删除
*/
void PopTop(); /*
* 获取栈顶的自动释放池,并不会删除
*/
AutoreleasePool* PeekTop(); private:
AutoreleasePoolMarager();
~AutoreleasePoolMarager(); private:
static AutoreleasePoolMarager* s_instance;
std::stack<AutoreleasePool*> m_poolstack;
};

AutoreleasePoolLifecycleManager

这个类的作用就是利用其对象的生命周期,来入栈和出栈自动释放池

class AutoreleasePoolLifecycleManager {
public:
/*
* 构造函数中,入栈一个新的自动释放池(AutoreleasePool)
*/
AutoreleasePoolLifecycleManager() { AutoreleasePoolMarager::GetInstance()->PushNew(); } /*
* 析构函数中,出栈自动释放池
*/
~AutoreleasePoolLifecycleManager() { AutoreleasePoolMarager::GetInstance()->PopTop(); }
};

使用宏代替实例化AutoreleasePoolLifecycleManager对象

#define autorelease_newpool \
torch::AutoreleasePoolLifecycleManager __arplm_obj_;

原理和代码都比较简单,只要把几个类得关系理清楚就明白了。

C++模拟OC的多重自动释放池的更多相关文章

  1. OC对象,自动释放池,OC与C语言的区别

    在C语言中,编程都是面向过程的编程,每一个代码块都严格按照从上至下的顺序执行,在代码块之间同样也是这样, 但是在OC中往往不是这样,OC和C++.java等语言一样,都是面向对象的编程语言,在代码的执 ...

  2. OC 内存泄露 自动释放池

    花絮:看到下面的代码就想起这么一个调侃: 一个老程序员,功成名就,金盆洗手不在写代码后,决定练练书法.提笔思索良久后在纸上写下:Hello world! /********************** ...

  3. OC中对象元素的引用计数 自动释放池的相关概念

    OC中数组对象在是如何处理对象元素的引用计数问题的,同时介绍一下自动释放池的相关概念 一.数组对象是如何处理对象元素的引用计数问题[objc]  view plaincopy 1. //   2. / ...

  4. 63 (OC)* NSAutoreleasePool 自动释放池

    目录 0:ARC 1: 自动释放池 2:NSAutoreleasePool实现原理 3:autorelease 方法 4: Runloop和Autorelease的关系 5: Using Autore ...

  5. OC学习篇之---数组对象的引用计数问题和自动释放池的概念

    之前一片文章中我们介绍了OC中的两个关键字@property和@synthesize的使用的使用: http://blog.csdn.net/jiangwei0910410003/article/de ...

  6. OC之property和自动释放池

    property实例 property参数 自动释放池 一.property实例 1.前边的例子我们看到,我们在一个类中如果用到另外一个类的实例作为自己的成员变量时,通常需要在setter方法中,先r ...

  7. OC自动释放池autoreleasepool介绍

    自动释放池的机制是:它使得应用在创建新对象时,系统能够有效地管理应用所使用的内存. @autoreleasepool { statements } 在创建新对象时,并且系统未启动ARC特性,那么在使用 ...

  8. Autorelease自动释放池的使用

    Autorelease自动释放池的使用 使用ARC开发,只是在编译时,编译器会根据代码结构自动添加了retain.release和autorelease. MRC内存管理原则:谁申请,谁释放 遇到al ...

  9. 04-OC属性的使用、自动释放池、封装和继承

    目录: 一.IOS6声明式属性的使用 二.autoreleasepool自动释放池 三.封装.继承 回到顶部 一.IOS6声明式属性的使用 注:声明式属性默认情况下,并没有解决内存问题, 当使用@pr ...

随机推荐

  1. grunt入门讲解7:项目脚手架grunt-init

    grunt-init是一个用于自动创建项目脚手架的工具.它会基于当前工作环境和你给出的一些配置选项构建一个完整的目录结构.至于其所生成的具体文件和内容,依赖于你所选择的模版和构建过程中你对具体信息所给 ...

  2. ubuntu中启动VIM,以及学习VIM

    启动VIM:首先打开终端,然后输入vi回车,然后输入i或者a,进入. 学习VIM:首先打开终端,然后输入vimtutor回车,然后进入教程学习.

  3. Alpha阶段敏捷冲刺①Scrum 冲刺博客

    第 1 篇 Scrum 冲刺博客对整个冲刺阶段起到领航作用,应该主要包含三个部分的内容: 各个成员在 Alpha 阶段认领的任务 成员 任务 张晨晨 完成界面设计(前端) 黄登峰 完成界面设计(前端) ...

  4. 软工网络15团队作业8——Beta阶段冲刺合集

    博客链接集合 Beta阶段敏捷冲刺计划博客 Beta阶段冲刺第一天 Beta阶段冲刺第二天 Beta阶段冲刺第三天 Beta阶段冲刺第四天 Beta阶段冲刺第五天

  5. 数据库事务的四大特性以及4种事务的隔离级别-以及对应的5种JDBC事务隔离级别

    本篇讲诉数据库中事务的四大特性(ACID),并且将会详细地说明事务的隔离级别. 如果一个数据库声称支持事务的操作,那么该数据库必须要具备以下四个特性: ⑴ 原子性(Atomicity) 原子性是指事务 ...

  6. ASP.NET Core 2 学习笔记

    之前的ASP.NET网站,只要把*.html.*.css.*.jpg.*.png.*.js等静态文件放在项目根目录,默认都可以直接被浏览:但ASP.NET Core 小改了浏览静态文件的方式,默认根目 ...

  7. 传说中的WCF:消息拦截与篡改

    我们知道,在WCF中,客户端对服务操作方法的每一次调用,都可以被看作是一条消息,而且,可能我们还会有一个疑问:如何知道客户端与服务器通讯过程中,期间发送和接收的SOAP是什么样子.当然,也有人是通过借 ...

  8. 【uoj#311】[UNR #2]积劳成疾 dp

    题目描述 一个长度为 $n$ 的序列,每个数在 $[1,n]$ 之间.给出 $m$ ,求所有序列的 $\prod_{i=1}^{n-m+1}(\text{Max}_{j=i}^{j+m-1}a[j]) ...

  9. 【BZOJ1922】大陆争霸(最短路)

    [BZOJ1922]大陆争霸(最短路) 题面 BZOJ 洛谷 题解 最短路变形题. 定义\(dis\)表示最短路,\(d\)表示最早可以进入当前点的时间.显然\(d=max(max(dis_v,d_v ...

  10. 【BZOJ4205】卡牌配对

    Description 现在有一种卡牌游戏,每张卡牌上有三个属性值:A,B,C.把卡牌分为X,Y两类,分别有n1,n2张. 两张卡牌能够配对,当且仅当,存在至多一项属性值使得两张卡牌该项属性值互质,且 ...