内存管理、copy、深浅拷贝

来源:互联网 发布:a10攻击机 知乎 编辑:程序博客网 时间:2024/06/06 16:48

内存管理、copy、深浅拷贝                                  

一、内存管理

1.内存管理的核心:谁分配、谁释放。

2.引用计数器加1的有:alloc、new、copy、retain。

3.引用计数器减1的有:release、autorelease。

注意:有retain就有release。

4.延迟释放(autorelease):和自动释放池配合使用,写在自动释放池生命周期以内。

   1)在什么时候可以使用延迟释放?

          带有延迟释放的对象。如传递参数。在释放池生命周期结束之后释放。

示例:

      NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];//初始化自动释放池

        Person *huLuWa = [[[Person alloc]init]autorelease];

        [pool release];

5.变量的生命周期

    1)局部变量的生命周期

      从定义位置开始到定义位置存在的括号以内。

     2)全局变量的生命周期

       对象只要存在全局变量就可以使用。

6.系统中需要管理内存数据和系统中不需要管理内存的数据

     1)不需要管理内存的数据(系统管理)

       分配在栈里面的数据(基本数据类型)。

       2)需要管理内存的数据

       分配在堆里面的。

7.setter、getter方法的内存管理

1)除了基本数据类型都有retain。

2)非原子性(nonatomic):在多线程的情况下不保证在不同线程数据的安全。

3)原子性(atomic) :在多线程里面保证数据的安全。


4)只要不使用多线程就用 nonatomic。

@property (nonatomic, retain) NSMutableArray *list;

5)基本数据类型使用assign

@property (nonatomic, assign) int age;


8.ARC情况下

1)如果这个对象在内存不足的时候,允许它被销毁掉。我们用 unsafe_unretained。

2)如果这个对象在内存不足的时候,不允许它被销毁掉。我们用 strong。

@property (nonatomic, unsafe_unretained) Dog *name;

@property (nonatomic, strong) Dog* age1;


二、copy

1.copy:会生成一个新的对象。给新的对象引用计数+1。

2.copy与retain的区别

    1)retain只会给原来的对象引用计数+1,不会生成新的对象。

    2)copy会生成一个新的对象。给新的对象引用计数+1。

3.如何实现

        Person *p = [[Person alloc]init];

        Person *p1 =  [p copy];

        [p1 release];

        [p release];

在Person.m中需要自定义拷贝功能

- (id)copyWithZone:(NSZone *)zone{

        Person *对象名 = [[Person allocWithZone:zone]init];

        对象名.属性名 = self.属性名;

        对象名.属性名 = self.属性名;

        ….

        return 对象名;   

}


3.自定义拷贝:除了字符串、数组、字典和NSNumber,其他的都需要自定义拷贝的功能  (遵守拷贝协议)。


三、深浅拷贝

1.深拷贝:完全拷贝一个对象。和原来的对象完全是两个个体。

2.浅拷贝:只拷贝对象本身,不拷贝对象里面的内容。

3.判断深浅拷贝的依据?

    看它们(不止对象本身 ,也包含对象里面的具体的内容)的内存地址是否一样。

4.浅拷贝

       Person *p =[[Person alloc]init];

        NSArray *array = [NSArray arrayWithObject:p];

        NSArray *array1 = [array copy];

        NSLog(@"拷贝之前: %p", array[0]);

        NSLog(@"拷贝之后: %p", array1[0]);

注意:copy mutableCopy 系统默认的是浅拷贝。

5.深拷贝

1)自定义的mutableCopy拷贝 深拷贝

- (id)mutableCopyWithZone:(NSZone *)zone{

Person *mutableCopyPer = [[Person allocWithZone:zone]init];

//    如果使用copy会把可变数组 变成不可变数组

    mutableCopyPer.list = [self.list mutableCopy];

    mutableCopyPer.age = self.age;

    return mutableCopyPer;

}


示例:Person *p1 = [p mutableCopy];

        NSLog(@"深拷贝之前: %p", p);

        NSLog(@"深拷贝之后: %p", p1);

2)数组的深拷贝(不需要自定义mutableCopy,因为数组里面已经有深拷贝的协议) 

      NSArray *array2 = [[NSArray alloc]initWithArray:array copyItems:YES];

     设置成YES就是深拷贝

        NSLog(@"深拷贝之前: %p", array[0]);

        NSLog(@"深拷贝之后: %p", array2[0]);


3)字典深拷贝 

        NSDictionary *dic = @{@"key":p};

        NSDictionary *dic1 = [[NSDictionary alloc]initWithDictionary:dic copyItems:YES];

       设置成YES就是深拷贝

        NSLog(@"字典拷贝之前: %p", dic[@"key"]);

        NSLog(@"字典拷贝之后: %p", dic1[@"key"]);

        

        

4)深拷贝的其他方式

     sqlite3、coreDara、 plist、 归档和文件操作。

6. 如果想让一个不可变对象变成一个可变对象 可以使用mutableCopy

        NSArray *list = @[@"1", @"2", @"3"];

        NSMutableArray *rec = [list mutableCopy];

        [ rec removeLastObject];

        NSLog(@"%@", rec);

        

7.如果对一个可变的对象进行 copy 它将变成一个不可变的对象,所以不能使用copy 必须使用mutableCopy。

        NSMutableString *string = [NSMutableString stringWithString:@"abcdef"];

注意:NSMutableString *recString = [string copy];这里不能使用copy 必须使用mutableCopy

    NSMutableString *recString = [string mutableCopy];

如果使用了copy,运行之后系统将会报以下错误

reason: '-[NSTaggedPointerString appendString:]: unrecognized selector sent to instance 

   

        [recString appendString:@"ghi"];

        NSLog(@"%@", recString);

        

0 0
原创粉丝点击