【转】对cocos2d 之autorelease\ratain\release的理解

news/2024/7/20 14:47:01 标签: 游戏, 内存管理, java

原文链接:http://blog.sina.com.cn/s/blog_4057ab6201018y4y.html

Objective C内存管理进阶(二):理解autorelease:

http://www.cnblogs.com/MobileDevelop/archive/2010/07/19/1779138.html

 
看了上面博客中对autorelease的见解,对autorelease有了更深入的了解。但是还不是很理解,于是又看了代码。一开始对autorelease的“自动释放”的印象总是挥之不去。总是往java那样的完全自动释放那方面靠,于是第一感觉就错了。
 
以下仅针对 cocos2dx分析。
 
前言:
三种情况,引出问题
    new出来的对象需要释放,而释放时,如果有其他人引用了这个对象,再次使用这个对象时,则会导致无效指针报错。
    于是有了引用计数的施放管理机制。
 
    对于一个返回对象指针的方法。你若不看文档不看内部代码,你无法知道返回的这个指针需不需要你来释放。同样的对于将一个指针作为参数给一个方法后,你为犹豫我能不能施放这个指针。因为你不知道这个方法内部会不会将你的指针施放。
    于是有了谁拥有谁施放的施放管理思想。
 
    使用了上述管理机制和思想后,有些特定情况。比如方法内新建一个对象,然后返回对象时,按照谁拥有谁施放。对象是在方法内部新建的,方法退出前不再拥有,所以要在方法退出前释放。但是又要在退出时返回该对象。先返回还是先释放都是不对的。。。
    于是就有了autorelease。
 
 
1、release 和retain是配套的,释放管理是通过引用计数。
    每一个CCObject对象都有一个引用计数。retain()时引用计数+1,release()则-1.在release之后,若引用计数为0,便会调用delete this; 真正的释放自己的内存。
    CCObject新建的时候,引用计数默认为1.
 
2、release和retain的使用的指导思想是,谁拥有谁施放。
    对于一个需要释放的变量。他的生命中通过新建、传递参数、方法返回值出现在各种地方,然而只有有人需要长期存储他的引用时,即想要拥有他,才应该调用retain()。释放时则秉着“谁retain谁施放”,retain和release的调用次数要配套。
 
------------------------------------------------------
void class IhaveObjHandler()
{
public:
   ObjX* objHandler;
   static void iWantObjX(objX* o){ 
      objHandler = o;   // 位置2
      objHandler->retain();
   }
   IhaveObjHandler(){
      objHandler = NULL;
    }
   ~IhaveObjHandler(){
      if(objHandler != NULL){ objHanlder->release();}
    }
}
 
void dispatchObjX(){
    ObjX* obj = new ObjX(); // 位置1
    IhaveObjHandler::iWantObjX( obj );
    obj->release();
}
------------------------------------------------------
示例中:需要释放管理的对象是 ObjX , 他在位置1新建,在位置2被传入到IhaveObjHandler。
位置1:因为obj新建时引用计数为1,而我(dispatchObjX方法)是不需要ObjX对象的,所以当我把他传给IhaveObjHandler 之后,我便释放他。
位置2:IhaveObjHandler里需要保存 ObjX的引用,于是我(IhaveObjHandler类)调用retain()。当我不需要他,想要把他释放的时候调用release().
在释放的时候,注意自己retain几次,只能释放几次,不能过多释放。
 
 
3、autoreleas是一个特殊的release,即延后释放。
    对比上面的dispatchObjX方法
------------------------------------------------------
ObjX* createObjX(){
    ObjX* obj = new ObjX(); 
    obj->autorelease();   //位置3 如果改成 obj->release();则obj的引用计数为0,会被释放。
    return obj;
}
------------------------------------------------------
    上面示例是一个产生新对象的方法。经常会用到,如果按照上述的释放管理思想,如位置3的注释写的那样。会在方法返回之前被释放。于是有了autorelease。
    autorelease其实只是为obj设置一个标记,延后释放。在之后的某一时刻,对obj的autorelease标记做处理(即释放)。上面示例中autorelease不是立即减少obj引用计数,则方法可以安全return obj;。
 
4、autoRelease实现原理的小细节
    关键字CCAutoreleasePool
    autorelease的对象会加入到从池中,最迟会在每个主循环结束前释放。
    池是用栈形式管理的。在适当情况下新建一个自动释放池,加入到栈中。所有要释放的对象都会加入到当前栈顶的这个池中,在特定情况(如每次主循环结束前),将池出栈。出栈时,做一些释放池中对象的处理。
 
    当CCObject释放时,如果该对象仍在自动释放池中,则从池中删除自己。
    同一个对象多次autorelease()的话,会被多次加入池中。池中对象存储结构是CCMutableArray,也就是vector.
 
5、 使用autorelease的好处
 
    1、new出来的对象的释放问题解决了。符合谁拥有谁释放的原则。
    2、可以避免频繁申请/释放内存  //ttun注:(没想出来,是什么意思

 

 
6、其实autorelease并没有那么好用
    综上,autorelease只不过解决了前言中及第三条说的引用计数的那个使用上的问题。对于引用计数本质没有太大改变。
    我们依旧要很 小心小心小心的注意释放对象的引用计数的变化。如果引用计数乱了一个的话,会导致报错。而且一旦因引用报错后,一般情况你是无法立即知道是哪里的引用除了问题。
    另外, 使用了引用计数的话,释放对象时别用delete, 而使用release()。

转载于:https://www.cnblogs.com/newcj/p/3850056.html


http://www.niftyadmin.cn/n/603804.html

相关文章

经典的正则表达式(转摘)

经典正则表达式 版权声明:CSDN是本Blog托管服务提供商。如本文牵涉版权问题,CSDN不承担相关责任,请版权拥有者直接与文章作者联系解决。关键字:正则表达式 模式匹配 Javascript摘要:收集一些常用的正则表达式。正则表…

《android上传图片》

2019独角兽企业重金招聘Python工程师标准>>> 这是主函数 package com.zmb.updemo; import java.io.BufferedReader; import java.io.DataOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.InputStream; import java.io.InputStr…

node.js小结 2

下载node安装npm什么的就不说了 入门总结 http://www.cnblogs.com/Darren_code/archive/2011/10/31/nodejs.html 进入node_HOME目录 test.js /*var hello require(./hello.js); console.log(hello.location : hello.location) console.log(hello.location : hello.name) h…

大话数据中心双活

投资界有一句至理名言——“不要把鸡蛋放在同一个篮子里”。说的是投资需要分解风险,以免孤注一掷失败之后造成巨大的损失。同样近年来自然灾害的频发为各行业的安全敲醒了警钟,对于IT系统来说如何通过灾备保证系统安全及业务连续性成为广大IT人关注的问…

NPOI 2.1.1 系列(2) 使用NPOI读取List或者datatable数据生成 Excel文档 ;Npoi生成 xlsx 2007以上文档...

结合上一篇文章 NPOI 2.1.1 系列(1) 使用NPOI读取 Excel文档 ;NpoiExcelHelper 导入导出 2003格式 2007格式的 Excel; Npoi 导出 xlsx 格式 以及 List转DataTable(反射) ; 将泛型集合类转换成DataTable ; 将集合类转换成DataTable 我们就能很方便的吧一个 List 给生成 Excel…

python输出最长字符串_python实现求两个字符串的最长公共子串方法

如下所示:# coding:utf-8求两个字符串的最长公共子串思想:建立一个二维数组,保存连续位相同与否的状态def getNumofCommonSubstr(str1, str2):lstr1 len(str1)lstr2 len(str2)record [[0 for i in range(lstr21)] for j in range(lstr11)]…

oracle数据库各种命令

-------------------基本命令---------------------------- sqlplus / as sysdba--命令行打开oracle(以dba身份登录) drop user myusers cascade;--删除用户(级联) create user myusers identified by 123;--创建用户(…

java常用注解_java项目常用注解

Autowired 自动注入 (存在多个可注入Bean时,通过 Qualifier 指定)Resource与Autowired作用相同Repository 只能标注在 DAO 类上。该注解的作用不只是将类识别为 Bean,同时它还能将所标注的类中抛出的数据访问异常封装为 Spring 的数据访问异常类型Compon…