Code Bye

关于obj-c的retain

 

我看了教材里面,所有的@property (nonatomic,retain)xxx的成员,在初始化的时候都是这样写的:

NSString *path = [[NSBundle mainBundle]pathForResource:@"sortednames" ofType:@"plist"];
    NSDictionary *dict = [[NSDictionary alloc]initWithContentsOfFile:path];
    self.names=dict;
    [dict release];
    NSArray *arr = [[names allKeys]sortedArrayUsingSelector:@selector(compare:)];
    self.keys = arr;

难道不能写成这样吗:

NSString *path = [[NSBundle mainBundle]pathForResource:@"sortednames" ofType:@"plist"];
    self.names = [[NSDictionary alloc]initWithContentsOfFile:path];
    self.keys = [[names allKeys]sortedArrayUsingSelector:@selector(compare:)];

20分
http://blog.csdn.net/NickTang写成这样会造成内存泄漏的, self.names = [[NSDictionary alloc]initWithContentsOfFile:path];这样的一句话,先执行=后面的部分,申请一块内存,并且内存计数器初始化为1,然后执行=操作,等号操作的左边是self.names,就是调用names的setter函数,而names在声明的时候,使用了retain修饰符,那么在它的setter函数中会对新的内存地址做一次retain,这样就造成这块内存的内存计数器为2,剩下的你自己考虑了。
如果你需要更进一步的资料,请访问我的博客。http://blog.csdn.net/NickTang
不可以,每次赋值都多分配了一次内存。
self.names = [[NSDictionary alloc]initWithContentsOfFile:path];
右边[[NSDictionary alloc]initWithContentsOfFile:path]; 会使retainCount+1,这个应该知道,没问题吧。
而在左边的self.names属性的setter内部也多了一次retainCount+1 (属性names的setter方法由编译器运行时生成)
其真实的实现如下:
-(void)setnames:(NSString *)names
{
     [_names release];
     _names=[names retain]; //这里又多了一次retainCount+1
}
这时的retainCount为2
而我们在使用完属性后都会把属性release一次,这一次只会将引用计数变成了2-1=1 。只要引用计数不为0,这部分的内存永远不会被系统回收,容易造成内存泄露。
楼主要将self.names拆开来看。
self.names = [[NSDictionary alloc]initWithContentsOfFile:path];
这写法会造成内存泄露,但是如果后边的表达式是autorelease的就不会有问题。

2楼


CodeBye 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权 , 转载请注明关于obj-c的retain