使用过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. UDJC用户自定义Java类

    private RowSet t1 = null;//业务表步骤 private RowSet t2 = null;//删除步骤 public boolean processRow(StepMetaI ...

  2. php单例模式 (转

    假设我们需要写一个类用来操作数据库,并同时满足以下要求: ①SqlHelper类只能有一个实例(不能多)②SqlHelper类必须能够自行创建这个实例③必须自行向整个系统提供这个实例,换句话说:多个对 ...

  3. PHP-时间函数

    1.时间格式化函数date(format,timestamp) format 时间格式 timestamp 时间戳 下面列出了一些常用于日期的字符: d - 表示月里的某天(01-31) m - 表示 ...

  4. [转帖]升级 Ubuntu,解决登录时提示有软件包可以更新的问题

    升级 Ubuntu,解决登录时提示有软件包可以更新的问题 2017年12月05日 11:58:17 阅读数:2953更多 个人分类: ubuntu Connecting to ... Connecti ...

  5. [转帖] Oracle JDK 11 正式发布.. 版本号真快

    Java 11 / JDK 11 正式发布! oschina 发布于 2018年09月26日 收藏 19 评论 38   在您的既有IT基础设施上按需构建人工智能更高效>>>   美 ...

  6. Implement Trie and find longest prefix string list

    package leetcode; import java.util.ArrayList; import java.util.List; class TrieNode{ Boolean isWord; ...

  7. MySQL命令行导入.sql文件遇到的问题

    导入.sql文件的命令行只有一句.但因为.sql文件大,在把本地的.sql文件导入到阿里云服务器的MySQL数据库时遇到了两个问题导入.sql文件的命令(假设数据库名为mydb,用户名root,密码1 ...

  8. Python学习---列表,元组,字典

    ### 列表 list = [1,2,3,4,5,6] list.append(7) print(list) ===>>> [1, 2, 3, 4, 5, 6, 7] list[2] ...

  9. vi写完文件保存时才发现是readonly😂

    在MAC上编辑apache配置文件,老是忘记sudo…… readonly的文件保存时提示 add ! to override, 但这仅是对root来说的啊! 百毒了一下竟然还有解决方案!! :w ! ...

  10. 【Cf #449 C】Willem, Chtholly and Seniorious(set维护线段)

    这里介绍以个小$trick$,民间流传为$Old Driver Tree$,实质上就是$set$维护线段. 我们将所有连续一段权值相同的序列合并成一条线段,扔到$set$里去,于是$set$里的所有线 ...