【木头Cocos2d-x 037】retain和release倒底怎么玩?

retain和release倒底怎么玩?

 

呼呼,好久没有发布教程了(小若:难得清静了,你为毛又出来吓人= =),其实最近木头我在准备出版书籍的事情。但是貌似不太顺利,果然我还是积累不够,写书的过程压力好大,感觉写不出有趣的文字出来(小若:嗷、、、)。果然还是在博客写自由一些?嘿嘿~

最近以及最不是很近(小若:书里一定不能出现这些错误的语句,所以你才写不出来吧= =),不少朋友对retain的认识似乎有点模糊,今天我就和大家分享一下关于retain的知识吧~

 

笨木头花心贡献,啥?花心?不呢,是用心~

转载请注明,原文地址
: http://blog.youkuaiyun.com/musicvs/article/details/8689345

正文:

 

 

 

1. 为什么会有retain?

C++和Java不一样,Java有一套很方便的垃圾回收机制,当我们不需要使用某个对象时,给它赋予null值即可。而C++new了一个对象之后,不使用的时候通常需要delete掉。

于是,Cocos2d-x就发明了一套内存管理机制(小若:发你妹纸。。。),其实红孩儿的博客很详细地解释了Cocos2d-x的内存管理机制,我没有能力也不想重复解释。(小若:那你还写?= =)

Retain的意思是保持引用,也就是说,如果想保持某个对象的引用,避免它被Cocos2d-x释放,那就要调用对象的retain函数。(小若:为什么不retain就会被释放?)

 

 

2. 真正的凶手autoRelease

既然旁白诚心诚意地问我,那我就光明正大地回答吧(小若:我今天没力气吐槽,好吧= =)。

一旦调用对象的autoRelease函数,那么这个对象就被Cocos2d-x的内存管理机制给盯上了,如果这个对象没人认领,那就等着被释放吧。(小若:= =太久没吐槽,一时不知道吐什么好)。

 

3. 看代码实际点

说了这么多,还是上代码吧。

创建一个Cocox2d-x的项目,就直接拿HelloWorldScene开刀,修改init函数,在最后添加一句代码:

  1. bool HelloWorld::init()  
  2. {  
  3.     bool bRet = false;  
  4.     do   
  5.     {  
  6.         /* 很多代码被省略了。。。。。。 */  
  7.   
  8.         testSprite = CCSprite::create("HelloWorld.png");  
  9.   
  10.         bRet = true;  
  11.     } while (0);  
  12.   
  13.     return bRet;  
  14. }  


 

(小若:testSprite是什么东东?)

testSprite是一个成员变量,在头文件里加上就可以了:

  1. class HelloWorld : public cocos2d::CCLayer  
  2. {  
  3. public:  
  4.     virtual bool init();    
  5.     static cocos2d::CCScene* scene();  
  6.     void menuCloseCallback(CCObject* pSender);  
  7.     CREATE_FUNC(HelloWorld);  
  8. private:  
  9.     cocos2d::CCSprite* testSprite;  
  10. };  


 

然后,最关键的来了,我们修改menuCloseCallback函数:

  1. void HelloWorld::menuCloseCallback(CCObject* pSender)  
  2. {  
  3.     testSprite->getPosition();  
  4. }  


 

现在,运行项目,点击按钮,看看是什么情况?

(小若:报错了!)

如果大家知道怎么调试项目的话,我们在menuCloseCallback函数里断点,用调试模式运行项目,看看testSprite对象:

(小若:很正常啊,有什么特别的?)

正你妹纸啊,正!你才正!(小若:不要这么光明正大地赞我O O!)

 

 

我们应该能看到不少非正常数据,图中已经用红色圈圈标出来了,这代表testSprite对象被释放了,现在testSprite指向未知的位置。

这是很危险的,有时候它不会立即报错,但是在某个时刻突然崩溃!

 

要想解决这个问题,很简单,再次修改init函数:

  1. bool HelloWorld::init()  
  2. {  
  3.     bool bRet = false;  
  4.     do   
  5.     {  
  6.         /* 很多代码被省略了。。。。。。 */  
  7.   
  8.         testSprite = CCSprite::create("HelloWorld.png");  
  9.   testSprite->retain();  
  10.     
  11.         bRet = true;  
  12.     } while (0);  
  13.   
  14.     return bRet;  
  15. }  


 

再次运行项目,看看还会不会报错?(小若:不会了,为什么?)

再次用调试模式运行项目,看看testSprite对象:

 

(小若:不正常!都是0!!)

零你妹纸= =(小若:为什么今天你总是抢我的对白O O!)

这次我们看到testSprite的数据明显正常了。

 

 

4. 原理来了

好了,唠叨了一大堆,还没有进入正题。

首先,要想让对象参与内存管理机制,必须继承CCObject类(CCNode、CCLayer等都继承了CCObject类)。

然后,调用对象的autoRelease函数,对象就会被Cocos2d-x的内存管理机制盯上,在游戏的每一帧,内存管理机制都会扫描一遍被盯上的对象,一旦发现对象无人认领,就会将对象杀死!(小若:嗷~残忍!)

如果不想让对象被杀死,那么就要调用对象的retain函数,这样对象就被认领了,一旦对象被认领,就永远不会被内存管理机制杀掉,是永远,一辈子。(小若:好朋友,一辈子= =)

但,对象一辈子都不被释放的话,那么就会产生内存泄露,你试试加载一个占20M内存的对象一辈子不释放,不折腾死才怪~(小若:你去加载一个20M的对象本身就是闲的那个什么疼啊!)因此,当你不需要再使用这个对象时,就要调用对象的release函数,这是和retain对应的。一般可以在析构函数里调用release函数。

 

 

5. 实际情况

讲道理,大家都懂,但是,相信很多朋友在实际写代码的时候,还是会感觉很混乱。

比如,什么时候该retain?大家是不是发现,有时候不retain也不会报错?

其实这很简单,因为我们经常会在create一个对象之后,添加到层里,如:

testSprite = CCSprite::create("HelloWorld.png");

this->addChild(testSprite);

addChild函数就是导致大家混乱的凶手了,addChild函数会调用对象的retain函数,为什么它要调用对象的retain函数呢?因为你都把对象送给它当孩子了,它当然要认领这个对象了!(小若:我懂了,嗷!)

于是,当我们把对象addChild到CCLayer时(不一定是CCLayer,CCArray、CCNode都行),我们就不需要调用对象的retain函数了。

 

 

6. 那倒底什么时候要retain?

说了这么多,还是没有说清楚,什么时候要调用对象的retain。

很简单,当你把一个对象作为成员变量时,并且没有把对象addChild到另外一个对象时,就需要调用retain函数。

 

7. 最后的最后

一定要记住,必须要调用了对象的autoRelease函数之后,retain和release函数才会生效,否则,一切都是徒劳。

因此,十分建议使用create的方式创建对象,如:

  1. CCSprite* CCSprite::create(const char *pszFileName)  
  2. {  
  3.     CCSprite *pobSprite = new CCSprite();  
  4.     if (pobSprite && pobSprite->initWithFile(pszFileName))  
  5.     {  
  6.         pobSprite->autorelease();  
  7.         return pobSprite;  
  8.     }  
  9.     CC_SAFE_DELETE(pobSprite);  
  10.     return NULL;  
  11. }  


 

这些就是retain表面上的知识了,至于retain源码级别的解说,请到红孩儿的博客吧,强烈推荐~

vs code , 配置 claude code 插件, 默认选项 : --dangerously-skip-permission 摘要:本文介绍如何在VS Code中为Claude Code插件配置--dangerously-skip-permission参数,包含两种方法:图形界面设置(适合新手)和直接编辑settings.json(精准配置)。该参数会跳过权限检查,仅建议在本地测试环境中使用。配置后需通过命令面板验证参数是否生效,并注意安全风险,避免在生产环境使用。多参数配置时需用数组格式,不同版本插件可能键名略有差异。 阅读详情

相关推荐

嵌入式C开发必备:用Cursor规则搞定代码风格检查(附Pikachu项目实战)

本文以Pikachu开源项目为例,详细介绍了如何利用Cursor的AI代理规则系统,为嵌入式C开发项目配置一套完整的代码风格检查与规范执行方案。通过实战演示,指导开发者创建项目级规则,实现命名、格式、硬件抽象层及驱动开发的自动化规范,从而提升代码一致性、可维护性和团队协作效率。

weixin_29181861的博客 598

C++ retain() 介绍

retain :保持引用 打开链接

tangguowu1573的专栏 1415

CATIA二次开发CAA安装

安装资料在网盘里 Win7 64位 以下软件均已管理员身份运行: 1.安装vs2008->自定义安装->选择要安装的功能->Visual C+±>x64编译器和工具 1.2安装SP1 2.安装CATIA V5 R21->win7_XP->CATIA.P3.V5R21.Win64->setup.exe 2.1安装目录改为D盘 2.2环境目录位置默认 3.安装...

qq_39311458的博客 4631

cocos2dx学习笔记之retain()和release()函数简介

retain的意思就是保持引用,避免被cocos2d-x释放。与之对应的就是release(). 和c++中的new(),delete()有点类似。 不过在coscos中由于autorelease的存在,问题变得更加复杂。 autorelease 对象调用autorelease,对象就会被cocos2d-x的内存管理机制标记,在游戏的每一帧,内存管理机制都要扫描被标记的对象,如果引用计数为零

shitangdejiaozi的博客 4623

基于Android平台下的健康管理APP/基于android的健康管理系统

随着网络科技的发展,移动智能终端逐渐走进人们的视线,相关应用越来越广泛,并在人们的日常生活中扮演着越来越重要的角色。因此,关键应用程序的开发成为影响移动智能终端普及的重要因素,设计并开发实用、方便的应用程序具有重要的意义和良好的市场前景。Android技术作为当前最流行的操作平台,自然也存在着大量的应用服务需求。 本课题研究的是基于Android技术平台的健康管理APP,开发这款健康管理APP主要是为了帮助用户可以不用约束时间与地点进行所需信息。本文详细讲述了健康管理APP的界面设计及使用,主要包括界面的

m0_73706453的博客 1437

银河麒麟服务器操作系统V10SP3 U盘安装中“基础软件仓库错误”的排查与修复指南

本文针对在无网络环境下使用U盘安装银河麒麟服务器操作系统V10SP3时,遇到的“基础软件仓库错误”问题,提供了详细的排查与修复指南。核心解决方案是通过进入救援模式,使用lsblk命令确定U盘实际设备路径,并在系统引导时手动添加inst.repo内核参数来指定安装源,从而绕过安装程序的自动探测故障,确保安装流程顺利进行。

ik67890123的博客 1193

retain和release

如果继承自 cc.Class或其子类,那么jsb就引用了c++的内存。 这样就可能用到 retain和release 如果不调用c++层的方法,那么没必要用retain和release 因为c++层的内存和js层是独立管理的。 比如 ClassA = cc.Layer.extend(...); 如果不调用和c++层的layer相关的函数或属性【比如addChild

xiuzhentianting的博客 530

一篇文章带你快速入门 MATLAB

文章目录一、认识 MATLAB 界面二、MATLAB 的运行方式三、Matlab 中的窗口1. 命令窗口2. MATLAB的程序编辑窗口3. 工作空间窗口4. 命令历史窗口5. 图形窗口6. 当前目录窗口四、MATLAB的帮助系统1. 帮助命令2. 联机帮助五、其他知识补充1. MATLAB的搜索路径2. 变量命名规则3. M文件命名规则 一、认识 MATLAB 界面 在 MATLAB Desktop 中,工具条取代了菜单和工具栏。应用程序库收纳了 MATLAB 产品系列的应用程序,单一文件应用程序打包为一

南淮北安的博客 5126

C++ release retain代码

  class CC_DLL CCObject : public CCCopying { protected: // object id unsigned int m_uID; // count of refrence unsigned int m_uReference; // is the object autoreleased bool m_bMan...

459

Allegro16.6详细教程(二)

3-D Viewer,可以直接在allegro中看到board file的3-D顯示效果。3-D Viewer對於PCB Editor Products,只有環境變數中的OpenGL顯示功能開啟後才有效,而對於APD/SiP是無效的。2.3-D viewer是在一個獨立的視窗中打開的。3-D environment環境支援多種顯示內容的過濾,取景視角和顯示效果的選項,透過遊標可以直接控制放大,移動,翻轉等操作。

axingxiansen的博客 1917

使用everything出现mem_virtual_alloc(): Fatal Error: out of memory解决方案

本文主要介绍了使用everything出现mem_virtual_alloc(): Fatal Error: out of memory解决方案,希望能对使用everything的同学们有所帮助。 文章目录 1. 问题描述 2. 解决方案

weixin_43178406的博客 1万+

Cocos2d-x retain和release倒底怎么玩?

【木头Cocos2d-x 037】retain和release倒底怎么玩? 分类: 笨木头 Cocos2D-x 2013-03-18 22:15 5979人阅读 评论(32) 收藏 举报 cocos2dcocos2d-xretainreleaseautoRelease retain和release倒底怎么玩? 呼呼,好久没有发布教程了(小若:难得清静了,你为毛又...

weixin_30747253的博客 137

基于ESP32的智能健康监测系统开发

本文介绍了如何基于ESP32开发智能健康监测系统,从硬件选型、系统架构到软件实现的每一个环节。通过ESP32的Wi-Fi功能、传感器模块和云平台的结合,我们实现了实时健康数据监测、远程查看、报警等功能。系统的低功耗特性使得其适用于长期健康监测,能够为用户提供更便捷的健康管理方案。随着技术的不断发展,未来智能健康监测系统将进一步发展。例如,增加更多的传感器,提升数据分析能力,甚至通过人工智能算法来预测用户的健康趋势,为用户提供个性化的健康建议。

2201_76125393的博客 1104

cocos2dx-3.0(32) retain和release

~~~~我的生活,我的点点滴滴!!

破茧 1118

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

sas retain和_all_

sas小知识点: retain:对变量进行值的初始化和保留到下一个迭代步 all:从SAS日志中的数据步骤打印结果 put()函数:把数值型或字符型变量转为字符型变量 input()函数:将字符型变量转化为数值型变量 input:读取变量 put:在日志窗口显示变量的值 未使用retain:______ data d; put "初始化结果:" _all_; input x@@; put "逐步显...

u010970317的博客 2353

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

内存管理2----retain点语法

Objective-C学习之旅(四)----内存管理2----retain点语法⼀一、retain属性的主要作⽤用 1、O-C内存管理和点语法 1>OC内存管理正常情况要使⽤用⼤大量的retain和relrese操作 2>点语法可以减少使⽤用retain和release的操作⼆二、@property(retain)编译器如何申明 编译器对于@property中的retain展开是不⼀一样

u011437490的专栏 1497

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

copy, retain, assign , readonly , readwrite,strong,weak,nonatomic整理

copy:建立一个索引计数为1的对象,然后释放旧对象 对NSString 对NSString 它指出,在赋值时使用传入值的一份拷贝。拷贝工作由copy方法执行,此属性只对那些实行了NSCopying协议的对象类型有效。更深入的讨论,请参考“复制”部分。 retain:释放旧的对象,将旧对象的值赋予输入对象,再提高输入对象的索引计数为1 对其他NSObject...

weixin_33881050的博客 292

深(浅)复制与retain

一.copy的理解        copy就是复制,简单的说就是创建一个一摸一样的东西。但是再oc当中,复制是否和语言的理解一样呢?当然不是一样的。说的明白点,外观师一样的,但是地址却是不同的。        其实copy是包括浅复制(copy)和深复制(mutableCopy)。那么我们来说说深复制吧。通过xcode我们来看看copy吧。首先按住command并且用鼠标点击copy进入一到F

不良少年 522

retain和copy还有assign的区别

解释一: 举个例子: NSString *str = [[NSString alloc] initWithString:@'abc']; 上面一段代码会执行以下两个动作: 1 在堆上分配一段内存用来存储@'abc' ,比如:内存地址为0X1111 内容为 'abc' 2 在栈上分配一段内存用来存储str,比如:地址为0XAAAA 内容自然为0X1111

xiaoxuan415315的专栏 5045

Cocos2dx 之retain ,release

因为功能和接口和objective-c版本的差不多,所以在内存管理上也采用objective-c引用计数的机制来实现内存管理。仔细看了一下cocos2d-x的源代码,确实写的很好,代码组织得很工整。它们所有类都是继承自CCObject, CCObject有retain(), release()和autorelease()等方法,和objective-c上的NSObject用法一致。每当CCObje

流彩飞霞的专栏 959

retain和release实现探究

前面一篇文章,我们讲到了系统为了优化数字字符串等类型的数据存储新增了一种NSTaggedPointer类型,同时我们还发现,isa指针在经过优化后,提供了19个bit位用来存储引用计数的个数。但是如果超出了这个限制呢? 引用计数 其实在绝大多数情况下,仅用优化的isa_t来记录对象的引用计数就足够了,但是当对象被引用次数超过 2^19 限制时,就轮到SideTable出场了。 首先,我们先看下超出限制之后,系统是如何将引用计数转移的 retian // 等价于直接使用对象调用retain方法 inline

weixin_43180925的博客 759

cocos2d-x内存管理机制之autorelease()

一个经典的工厂方法如同这样:   CCObject* factoryMethod(){ CCObject* ret = new CCObject(); return ret; }  工厂方法对ret对象的引用在函数返回时已经结束,但是它没有释放对ret的引用,买下了内存泄露的隐患。但是如果在函数返回前就执行了release(),这显然是不适合的,因为这会触发对象的

u010393423的专栏 1836

cocos2dx中retain和release

cocos2dx中retain和release  1、要想让对象参与内存管理机制,必须继承CCObject类(CCNode、CCLayer等都继承了CCObject类)。   2、调用对象的autoRelease函数,对象将接受Cocos2d-x的内存管理机制监控,在游戏的每一帧,内存管理机制都会扫描一遍被盯上的对象,一旦发现对象没有被引用,就会被释放。   3、如果不想被释放,那么就

XUZHENG19860228的专栏 480

【cocos2dx】学习记录,Node的自动释放(autorelease)

在整理一个功能的时候,发现做了一个对象池用来缓存ScrollView的子节点,这里面手动的去retain和release对象池内的Node,碰到了一些小问题记录一下综上所述,我们已经可以很清楚的看明白cocos引用计数的原理Ref在被创建的时候,默认引用计数+1继承自Ref的Node在初始化的时候,会默认设置成autorelease被设置成autorelease状态的节点,如果引用计数

孙君的空间站 1066

cocos2dx[3.2]——内存管理机制

原文链接 https://www.cnblogs.com/timesdaughter/p/6693996.html Cocos2d-x 提供引用计数管理内存。 >调用retain()方法 :令其引用计数增1,表示获取该对象的引用权。 > 调用release()方法 :在引用结束的时候,令其引用计数值减1,表示释放该对象的引用权。 > 调用autorelease()方法 ...

hlmfjkqaz的专栏 386

cocos2d-x内存管理retain和release

cocos2d-x和objective-c中的retain()和release() 因为功能和接口和objective-c版本的差不多,所以在内存管理上也采用objective-c引用计数的机制来实现内存管理。仔细看了一下cocos2d-x的源代码,确实写的很好,代码组织得很工整。它们所有类都是继承自CCObject, CCObject有retain(), release()和autorelea

Jingle的专栏 1742
上一篇: cocos2dx JS localStorage
下一篇: cocos2dx继承结构图
mincheat
博客等级 码龄17年 46粉丝 43原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值