ImageVerifierCode 换一换
格式:DOCX , 页数:15 ,大小:20.18KB ,
资源ID:23593629      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/23593629.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(ObjectiveC内存管理课件.docx)为本站会员(b****7)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

ObjectiveC内存管理课件.docx

1、ObjectiveC内存管理课件Objective-C的内存管理机制琢磨不透初学objectice-C的朋友都有一个困惑,总觉得对objective-C的内存管理机制琢磨不透,程序经常内存泄漏或莫名其妙的崩溃。Objective-C 2.0增加了一些新的东西,包括属性和垃圾回收。那么,我们在学习Objective-C 2.0之前,最好应该先了解,从前是什么样的,为什么Objective-C 2.0要增加这些支持。这一切都跟Cocoa内存的管理规则有关系,我们知道,Objective-C中所有变量都定义为指针。指针是一个特殊的变量,它里面存储的数值被解释成为内存里的一个地址,如果使用不当,就会出

2、错或者造成内存的泄露。要了解这些,就需要看看其内存管理的规则到底是什么样的。Cocoa和Objective-C的类都是NSObject的子类。NSObject中有几个方法进行内存管理。alloc方法为对象分配一片内存空间。dealloc方法用于释放对象的空间。但是在我们的代码中将永远都不会使用dealloc方法(类似C+中的析构函数),因为运行时会为你调用此方法释放内存空间。而你需要做的只是引用计数。1Object release and reference countObjective-C的对象在使用完成之后不会自动销毁,需要执行dealloc来释放空间(销毁),否则内存泄露。obj1 re

3、lease;/release方法来自动调用对象的dealloc方法这带来了一个问题。下面代码中obj2是否需要调用dealloc?ClassA *obj1 = ClassA alloc init;ClassA *obj2 = obj1;obj1 hello; /输出helloobj1 release;obj2 hello; /能够执行这一行和下一行吗?obj2 release; 不能,因为obj1和obj2只是指针,它们指向同一个对象,obj1 dealloc已经销毁这个对象了,不能再调用obj2 hello和obj2 release。obj2实际上是个无效指针。 Objective-C采用了

4、引用计数(retain count)。对象的内部保存一个数字,表示被引用的次数。例如,某个对象被两个指针所指向(引用)那么它的retain count为2。需要销毁对象的时候,不直接调用dealloc,而是调用release。release会让retain count减1,只有retain count等于0,系统才会调用dealloc真正销毁这个对象。Foo*myFooOne=Fooallocinit;/retaincount为11. 2. Foo*myFooTwo=myFooOne;/myFooTwo指向了这个对象3. 4. /retaincount仍然为15. 6. myFooTworet

5、ain;/调用retain方法,运行时才知道myFooTwo指向了该对象,retaincount为2上面的代码中,myFooTwo通过调用retain方法,取得了Foo对象的拥有权。在这个对象的生命周期中,会有很多变量来指向和引用它。指向这个对象的变量也可以通过release方法来解除这种拥有权。release方法将会告诉运行时,我已经使用完这个变量了,已经不需要它了,retainCount计数减1。当对象的retainCount的计数大于或者等于1的时候,运行时会继续维持这个对象。当对象的retainCount为0的时候,运行时会释放这个对象,并回收它占得内存空间。myFooOne rele

6、ase; / myFooOne retaincount = 1; /myFooTwo retaincount = 1;myFooOne release; / myFooOne retaincount = 0; /myFooTwo retaincount = 0;2. autorelease poolObjective-C中引入了autorelease pool(自动释放对象池),在遵守一些规则的情况下,可以自动释放对象。新生成的对象,只要调用autorelease就行了,无需再调用release!ClassA *obj1 = ClassA alloc init autorelease; /re

7、tain count = 1 但无需调用release对于存在指针赋值的情况,代码与前面类似。ClassA *obj1 = ClassA alloc init autorelease; /retain count = 1ClassA *obj2 = obj1; /retain count = 1obj2 retain; /retain count = 2obj1 hello; /输出hello/对于obj1,无需调用(实际上不能调用)releaseobj2 hello; /输出helloobj2 release; /retain count = 2-1 = 1autorelease pool原

8、理剖析。(其实很简单的,一定要坚持看下去,否则还是不能理解Objective-C的内存管理机制。)autorelease pool不是天生的,需要手动创立。只不过在新建一个iphone项目时,xcode会自动帮你写好。autorelease pool的真名是NSAutoreleasePool。NSAutoreleasePool *pool = NSAutoreleasePool alloc init;NSAutoreleasePool内部包含一个数组(NSMutableArray),用来保存声明为autorelease的所有对象。如果一个对象声明为autorelease,系统所做的工作就是把这

9、个对象加入到这个数组中去。ClassA *obj1 = ClassA alloc init autorelease;/retain count = 1把此对象加入autorelease pool中NSAutoreleasePool自身在销毁的时候,会遍历一遍这个数组,release数组中的每个成员。如果此时数组中成员的retain count为1,那么release之后,retain count为0,对象正式被销毁。如果此时数组中成员的retain count大于1,那么release之后,retain count大于0,此对象依然没有被销毁,内存泄露。 默认只有一个autorelease p

10、ool,通常类似于下面这个例子。int main (int argc, const char *argv)NSAutoreleasePool *pool;pool = NSAutoreleasePool alloc init; / do something pool release;return (0); / main所有标记为autorelease的对象都只有在这个pool销毁时才被销毁。如果你有大量的对象标记为autorelease,这显然不能很好的利用内存,在iphone这种内存受限的程序中是很容易造成内存不足的。例如:int main (int argc, const char *ar

11、gv)NSAutoreleasePool *pool = NSAutoreleasePool alloc init;int i, j;for (i = 0; i 100; i+ ) for (j = 0; j 100000; j+ ) NSString stringWithFormat:1234567890;/产生的对象是autorelease的。pool release;return (0); / main二 口诀与范式1口诀1.1 谁创建,谁释放(类似于“谁污染,谁治理”)。如果你通过alloc、new或copy来创建一个对象,那么你必须调用release或autorelease。换句话说

12、,不是你创建的,就不用你去释放。例如,你在一个函数中alloc生成了一个对象,且这个对象只在这个函数中被使用,那么你必须在这个函数中调用release或autorelease。如果你在一个class的某个方法中alloc一个成员对象,且没有调用autorelease,那么你需要在这个类的dealloc方法中调用release;如果调用了autorelease,那么在dealloc方法中什么都不需要做。1.2除了alloc、new或copy之外的方法创建的对象都被声明了autorelease。1.3谁retain,谁release。只要你调用了retain,无论这个对象是如何生成的,你都要调用r

13、elease。有时候你的代码中明明没有retain,可是系统会在默认实现中加入retain。不知道为什么苹果公司的文档没有强调这个非常重要的一点,请参考范式2.7和第三章。2范式范式就是模板,就是依葫芦画瓢。由于不同人有不同的理解和习惯,我总结的范式不一定适合所有人,但我能保证照着这样做不会出问题。2.1 创建一个对象。ClassA *obj1 = ClassA alloc init;2.2 创建一个autorelease的对象。ClassA *obj1 = ClassA alloc init autorelease;2.3 Release一个对象后,立即把指针清空。(顺便说一句,releas

14、e一个空指针是合法的,但不会发生任何事情)obj1 release;obj1 = nil;2.4 指针赋值给另一个指针。ClassA *obj2 = obj1;obj2 retain;/do somethingobj2 release;obj2 = nil;2.5在一个函数中创建并返回对象,需要把这个对象设置为autoreleaseClassA *Func1() ClassA *obj = ClassA allocinitautorelease; return obj;2.6在子类的dealloc方法中调用基类的dealloc方法-(void) dealloc super dealloc;2.

15、7在一个class中创建和使用property。2.7.1声明一个成员变量。ClassB *objB;2.7.2 声明property,加上retain参数。property (retain) ClassB* objB;2.7.3 定义property。(property的默认实现请看第三章)synthesize objB;2.7.4 除了dealloc方法以外,始终用.操作符的方式来调用property。self.objB 或者objA.objB2.7.5 在dealloc方法中release这个成员变量。objB release;interface ClassA : NSObject Cl

16、assB* objB; property (retain) ClassB* objB;end implementation ClassAsynthesize objB;-(void) dealloc objB release; super dealloc;end2.7.6 给这个property赋值时,有手动release和autorelease两种方式。void funcNoAutorelease() ClassB *objB1 = ClassB allocinit; ClassA *objA = ClassA allocinit; objA.objB = objB1; objB1 rele

17、ase; objA release; void funcAutorelease() ClassB *objB1 = ClassB allocinit autorelease; ClassA *objA = ClassA allocinit autorelease; objA.objB = objB1;三 property (retain)和synthesize的默认实现在这里解释一下property (retain) ClassB* objB;和synthesize objB;背后到底发生了什么(retain property的默认实现)。property实际上是getter和setter,针

18、对有retain参数的property,背后的实现如下:interface ClassA : NSObject ClassB *objB; -(ClassB *) objB;-(void) setObjB:(ClassB *) value;end implementation ClassA-(ClassB*) objB return objB; -(void) setObjB:(ClassB*) value if (objB != value) objB release; objB = value retain; 在setObjB中,如果新设定的值和原值不同的话(如果相同怎么办?可以测试一下)

19、,必须要把原值对象release一次,这样才能保证retain count是正确的。由于我们在class内部retain了一次(虽然是默认实现的),所以我们要在dealloc方法中release这个成员变量。-(void) dealloc objB release; super dealloc;property中使用assign,retain,copy的区别(需要先讲一下copy协议)/MyPoint.h#import interface MyPoint : NSObject int x; int y;property (nonatomic) int x,y;-(void) setMyPoin

20、t:(int)_x andY:(int)_y;end/MyPoint.m#import MyPoint.himplementation MyPointsynthesize x,y;-(void) setMyPoint:(int)_x andY:(int)_y x = _x; y = _y;end/ Circle.h#import #import MyPoint.hinterface Circle : NSObject MyPoint *p; int radius;property (nonatomic, assign) MyPoint *p;-(id) initP:(MyPoint *)_p

21、andRad:(int)_r;-(void )print;end/ Circle.m#import Circle.himplementation Circlesynthesize p;-(id) initP:(MyPoint *)_p andRad:(int)_r /初始化第一步 if(_r0) radius = 1; if(_p = nil)/#1 self release; return nil; /初始化第二步 if(!(self = super init)/#2 return nil; /初始化第三步 / _p retain; / p = _p; if(p) p release; p

22、=MyPoint alloc init; p setMyPoint:_p.x andY:_p.y; radius = _r; return self;-(void)dealloc super dealloc; if (p) p release; -(void )print NSLog(r = %d,radius);endint main (int argc, const char * argv) NSAutoreleasePool * pool = NSAutoreleasePool alloc init; /insert code here. MyPoint *p = MyPoint all

23、oc init; NSLog(P:%lu,p retainCount); /1 Circle *c = Circle alloc init; NSLog(c:%lu,c retainCount); /1 pool drain; return 0;1, property (nonatomic, assign) MyPoint *p;主函数中加入以下代码:c.p = p; /c.p retainCount为多少?p retainCount =?c.p和p是深拷贝or浅拷贝?c.p retainCount= 1?p retainCount =1浅拷贝 , 2,把property中assign找成re

24、tain ,c.p retainCount又为多少?p retainCount?c.p和p是深拷贝or浅拷贝?c.p retainCount= 2?p retainCount =2浅拷贝 , 3,改为copy呢?c.p retainCount = ?p retainCount = ?c.p和p是深拷贝or浅拷贝?c.p retainCount= 1?p retainCount =1深拷贝 , 4,在主函数中把c.p = p; 换成c.p = p copy; property属性中分别用assign,retain,copy再进行测试,结果又如何?中间是否有内存泄露问题?c.p和p是深拷贝or浅拷

25、贝?Assign:c.p retainCount= 1?p retainCount =1深拷贝 ,不会有内存泄露。Retain:c.p retainCount= 2?p retainCount =1深拷贝 ,不会有内存泄露。Copy:c.p retainCount= 1?p retainCount =1深拷贝 ,会有内存泄露。 5,把-(id) initP:(MyPoint *)_p andRad:(int)_r实现中的p的初始化改为p = _p后,再分别重复以上四种情况下c.p retainCount和p retainCount各是多少?c.p和p是深拷贝or浅拷贝?如果初始化方法不变的话,

26、都将不会变。如果初始化方法换成 -(id) initP:(MyPoint *)_p andRad:(int)_rc.p=p; 1)、assign: c.p retainCount= 1?p retainCount =1浅拷贝 ,2)、retain:c.p retainCount= 1?p retainCount =1浅拷贝 ,3)、copy:c.p retainCount= 1?p retainCount =1深拷贝 ,c.p = p copy;1)、assign: c.p retainCount= 1?p retainCount =1浅拷贝2)、retain:c.p retainCount= 2?p retainCount =1浅拷贝3)、copy:c.p retainCount= 1?p retainCount =1深拷贝 ,

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1