欢迎来到天天文库
浏览记录
ID:11696045
大小:46.00 KB
页数:3页
时间:2018-07-13
《从 c++ 到 objective-c(15):内存管理(续二)》由会员上传分享,免费在线阅读,更多相关内容在行业资料-天天文库。
1、从C++到Objective-C(15):内存管理(续二)作者: DevBean 日期:2011年03月31日发表评论 (3)查看评论Setters如果不对Objective-C的内存管理机制有深刻的理解,是很难写出争取的setter的。假设一个类有一个名为title的NSString类型的属性,我们希望通过setter设置其值。这个例子虽然简单,但已经表现出setter所带来的主要问题:参数如何使用?不同于C++,在Objective-C中,对象只能用指针引用,因此setter虽然只有一种原型,但是却可以有很多种实现:可以直接指定,可以使用retain指定,
2、或者使用copy。每一种实现都有特定的目的,需要考虑你set新的值之后,新值和旧值之间的关系(是否相互影响等)。另外,每一种实现都要求及时释放旧的资源,以避免内存泄露。直接指定(不完整的代码)外面传进来的对象仅仅使用引用,不带有retain。如果外部对象改变了,当前类也会知道。也就是说,如果外部对象被释放掉,而当前类在使用时没有检查是否为nil,那么当前类就会持有一个非法引用。-(void)setString:(NSString*)newString{...稍后解释内存方面的细节self->string=newString;//直接指定}使用retain指定(
3、不完整的代码)外部对象被引用,并且使用retain将其引用计数器加1。外部对象的改变对于当前类也是可见的,不过,外部对象不能被释放,因为当前类始终持有一个引用。-(void)setString:(NSString*)newString{...稍后解释内存方面的细节self->string=[newStringretain];//使用retain指定}复制(不完整的代码)外部对象实际没有被引用,使用的是其克隆。此时,外部对象的改变对于当前类是不可变的。也就是说,当前类持有的是这个对象的克隆,这个对象的生命周期不会比持有者更长。-(void)setString:(
4、NSString*)newString{...稍后解释内存方面的细节self->string=[newStringcopy];//克隆//使用NSCopying协议}为了补充完整这些代码,我们需要考虑这个对象在前一时刻的状态:每一种情形下,setter都需要释放掉旧的资源,然后建立新的。这些代码看起来比较麻烦。直接指定(完整代码)这是最简单的情况。旧的引用实际上被替换成了新的。-(void)setString:(NSString*)newString{//没有强链接,旧值被改变了self->string=newString;//直接指定}使用retain指定(
5、完整代码)在这种情况下,旧值需要被释放,除非旧值和新值是一样的。//------不正确的实现-------(void)setString:(NSString*)newString{self->string=[newStringretain];//错误!内存泄露,没有引用指向旧的“string”,因此再也无法释放} -(void)setString:(NSString*)newString{[self->stringrelease];self->string=[newStringretain];//错误!如果newString==string(这是可能的),//
6、newString引用是1,那么在[self->stringrelease]之后//使用newString就是非法的,因为此时对象已经被释放} -(void)setString:(NSString*)newString{if(self->string!=newString)[self->stringrelease];//正确:给nil发送release是安全的self->string=[newStringretain];//错误!应该在if里面//因为如果string==newString,//计数器不会被增加} //------正确的实现------//最佳
7、实践:C++程序员一般都会“改变前检查”-(void)setString:(NSString*)newString{//仅在必要时修改if(self->string!=newString){[self->stringrelease];//释放旧的self->string=[newStringretain];//retain新的}} //最佳实践:自动释放旧值-(void)setString:(NSString*)newString{[self->stringautorelease];//即使string==newString也没有关系,//因为release是
8、被推迟的self->string=[n
此文档下载收益归作者所有