【Lession 11 OC语言】- 内存管理2-retain,assign,copy

本节目录

 

retain

先建一个student类,和一个Book类,学生拥有有一本书

Book.m

#import "Book.h"

@implementation Book


-(void)dealloc{
    NSLog(@"Book 被销毁");
    [super dealloc];
}
@end

 

Student.h,nonatomic先不理,后面来讲

#import <Foundation/Foundation.h>
#import "Book.h"
@interface Student : NSObject

@property(nonatomic,retain)Book *book;

@end

 

 

int main(int argc, const char * argv[])
{
    @autoreleasepool {
        Student *stu = [[Student alloc] init];
        
        Book *book = [[Book alloc] init];
        stu.book = book;
        
        //打印的结果变成2,说明,retain声明的属性的引用计数器为+1
        NSLog(@"book returnCount: %lu",[book retainCount]);
        
        [book release];
        [stu release];
    }
    return 0;
}

 

打印的结果变成2,好,那我们看下有retain的set方法是怎么做的

#import "Student.h"

@implementation Student


-(void)setBook:(Book *)book{
    
    //如果传进的book对像跟已经持有book对象不相等,这时我们就替换原有的book对象为传进来的book对象
    if (_book != book) {
        //先release以前的book对象,释放内存
        [_book release];
        //return下,持有book对象
        _book = [book retain];
    }
}

@end

 

总结:retain会使引用计数器加1,谁持有对象,就要对对象进行释放操作

 

上面的代码还有问,我们还应该在Student的dealloc方法进行book的释放操作,永远记住,谁持有对象,就要对它负责

#import "Student.h"

@implementation Student


-(void)setBook:(Book *)book{
    
    //如果传进的book对像跟已经持有book对象不相等,这时我们就替换原有的book对象为传进来的book对象
    if (_book != book) {
        //先release以前的book对象,释放内存
        [_book release];
        //return下,持有book对象
        _book = [book retain];
    }
}

-(void)dealloc{
    [_book release];
    [super dealloc];
}

@end

 

这样在执行main方法时,Book的dealloc方法才会被调用,才证明book已经被释放了。

结果

2014-03-17 18:01:25.827 HellowWord_OC[2243:303] book returnCount: 2
2014-03-17 18:01:25.829 HellowWord_OC[2243:303] Book 被销毁

 

 

assign

把student持有的book的retain属性变成assign,去掉student.m的set方法,运行main函数发现book被释放了。

这说明assign标识的属性没有把引用计数器加1,而是直接赋值,等效于下面

-(void)setBook:(Book *)book{
    
    //如果传进的book对像跟已经持有book对象不相等,这时我们就替换原有的book对象为传进来的book对象
    if (_book != book) {
        _book = book;
    }
}

 

copy

#import <Foundation/Foundation.h>
#import "Book.h"
#import "Student.h"

int main(int argc, const char * argv[])
{
    @autoreleasepool {
        
        Book *book = [[Book alloc] init];

        
        NSMutableArray *array1 = [NSMutableArray arrayWithObjects:book, nil];
        NSMutableArray *array2 = [array1 copy];
        NSMutableArray *array3 = [array1 retain];
        NSLog(@"array1 %p",array1);
        NSLog(@"array2 %p",array2);
        NSLog(@"array3 %p",array3);
        
        [array2 release];
        [array3 release];
        [book release];
    }
    return 0;
}

 

结果

2014-03-17 19:02:52.118 HellowWord_OC[2681:303] array1 0x10010be50

2014-03-17 19:02:52.120 HellowWord_OC[2681:303] array2 0x10010a9f0

2014-03-17 19:02:52.121 HellowWord_OC[2681:303] array3 0x10010be50

2014-03-17 19:02:52.121 HellowWord_OC[2681:303] Book 被销毁

 

看到array1array2两个的地址空间不一样array1array3内存地址一样,copy会开辟一个新的内存空间来存放传进来的数据,并且引用计数器为1

也就是说, copy  是内容拷贝, retain  是指针拷贝。 

 

 

 

什么时候用assign,什么时候用retain

>、int float long,char,BOOL等基本数据类型用assign,因为基本数据类型没有引用计数器的概念

>、NSString用copy.

>、其余的暂时用retain,到后面我们再在ios开发中哪些用assign

 

posted @ 2014-03-17 18:06  Vincent_Guo  阅读(367)  评论(0编辑  收藏  举报