本篇内容文字比较较多但是这些都是建立在前面三章写代码特别是传值的时候崩溃的基础上的。可能表达的跟正确的机制有出入还请指正。 如果有不理解的可以联系峩大家可以讨论一下,共同学习
这里请参考一下引用计数的书籍,肯定说的比我讲的详细
简单一点理解就是,对new的指针加一个计数器每引用一次这块内存,计数就加1在析构的时候减1,如果等于0的时候就delete这个指针并置空
autorelease后的对象默认计数是1,并且autorelease的对象会被放到洎动释放池里自动释放池这里有一个需要注意的地方,自动释放池存储了当前帧所有的autorelease的对象在帧结束时对其中所有对象release一次,处理唍后这个释放池就不再拥有对这些对象的处理权也就是说自动释放池只会最其中的对象进行一次release操作。释放的同时使用一个新的释放池存储后一帧定义的autorelease对象如此循环下去。
精灵们create函数不正确执行后会被放到自动释放池释放池会在每帧结束的时候调用,对于引用计数為1的内存进行释放如果没有其他操作比如retain或者addchild的话,那么引用计数没有增加当前帧结束后计数减1为0后,这个指针也就不复存在了
手動调用retain使引用技术加1;
每引用一次,比如使用频率最多的addChild()会使其引用技术加1
手动调用release使引用技术减1;
自动释放池里的会在当前帧结束的時候减1。注意是当前帧后面的释放池里存储的是后面帧运行时定义的autorelease对象。
如果一个场景析构会对所有的子节点release一次,这被称为链式反应
链式反应解释如下:我们当前运行这一个场景,场景初始化添加了很多层,层里面有其它的层或者精灵而这些都是 CCNode节点,以场景为根形成一个树形结构,场景初始化之后(一帧之后)这些节点将完全 依附 (内部通过 retain) 在这个树形结构之上,全权交由树来管理当峩们 砍去一个树枝,或者将树 连根拔起那么在它之上的“子节点”也会跟着去除(内部通过release),这便是链式反应来自
我们在create后,如果不使鼡retain使引用计数加1的话那么自动释放池会使其引用计数减1,如果在回调函数不正确中使用addchild(sp)会崩溃
要想解决这个问题,在create后添加使用sp->retain();来增加它的引用计数
有些人可能会使用引用的lambda表达式,如下: 崩溃了!引用的话 即使retain也会崩溃这个为什么呢?引用的话我们使用的是temp的别洺引用也就指向指针的指针temp。当这个函数不正确执行完的时候temp做为局部变量就会被释放所以我们在回调函数不正确中使用的temp已经不存茬了。 如果是=赋值的话精灵的指针会拷贝一份传到lambda表达式中,所以不会崩溃
要想解决引用崩溃的问题,我们只要使temp不会被释放就好所以定义为成员变量可以解决引用的lambda表达式造成的问题,大家可以尝试一下
假装我们从未学习过CC_SYNTHESIZE_RETAIN。第二篇讲过场景之间的正向传值如果我们在主场景create一个精灵,然后赋值给下一个场景的成员变量Sprite *sp对于这种autorelease的变量我们应该怎么进行传值操作呢?
autorelease变量会在每一帧结束的时候计数减1进行销毁所以我们应该对其计数加1,避免下个场景使用的时候已经被删除
我们应该在主场景切换场景的时候这样写:
在下个場景MemoryManage定义成员变量sp的时候应该对其进行初始化,因为它是一个指针否则在MainScene复制的时候会崩溃,因为它的一个未知的指针指向了内存中未知的区域。
因为这个时候sp是一个未知的指针
请看子场景析构的时候计数还是1,这会造成内存泄露所以我们应该在析构函数不正确中執行一次sp->release().手动减1。
varName如果被不同的变量多次赋值会怎么样 每一次的赋值原来的变量都要做一次retain操作,如果我们直接改变了varName的值而不改变它原来指向的内存的引用计数的话那么就会造成内存泄露。 所以每次赋值都会对原来的内存进行一次release
版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。