12.深浅拷贝

1.复制对象的基本概念

  1. 复制对象的基本概念:复制一个对象作为副本,它会开辟一块新的内存(堆内存)来存储副本对象,就像复制文件一样.即源对象和副本对象是两块不同的内存区域.
  2. 对象具备复制功能,必须实现协议,协议.常用的可复制对象有:NSNumber,NSString,NSArray,NSDictionary.NSMutableDictionary,NSMutableArray,NSMutablrString;
  3. 复制对象的种类: 1)copy:产生对象的副本是不可变的 2)mutableCopy:产生的副本对象是可变的

2.深浅拷贝的基本概念和用法

  1. 浅复制只复制对象的本身,对象里的属性和包含的对象不做复制.
  2. 浅复制则既复制对象本身,对象的属性也会复制一份Foundation框架中支持的复制的类,默认是浅复制
//两数组指向同一地址
NSMutableArray *array1 = [[NSMutableArray alloc] initWithObjects:@"one",@"two",@"three",@"foure", nil];
NSMutableArray *array2 = [array1 retain];
[array2 removeLastObject];
NSLog(@"%@",array1);//--->(one,two,three)
NSLog(@"%ld",array1.retainCount);//--->2

//两数组非同一地址
NSMutableArray *array1 = [[NSMutableArray alloc] initWithObjects:@"one",@"two",@"three",@"foure", nil];
NSMutableArray *array2 = [array1 mutableCopy];
[array2 removeLastObject];
NSLog(@"%@",array1);//--->(one,two,three,foure)

NSArray *array = @[@"one",@"two"];
//array1和array指向同一地址,copy出来的对象是不可变的
NSArray *array1 = [array copy];//不可变数组不能添加元素
NSMutableArray *array2 = [array mutableCopy];
[array2 addObject:@"three"];
NSLog(@"%@",array2);//--->(one,two,three)

例如:一个数组包含了许多个对象,复制一个数组的副本,那么两个数组中的元素是没有复制的,指向的还是同一个对象

NSMutableArray *array = [NSMutableArray array];
for (int i=0; i<3; i++) {
    NSObject *obj = [[NSObject alloc] init];
    [array addObject:obj];
    [obj release];
}

for (NSObject *obj in array) {
    NSLog(@"指针地址:%p, 引用计数:%ld",obj,obj.retainCount);
}   //--->指针地址:0x100202ad0, 引用计数:1
    //--->指针地址:0x100201a40, 引用计数:1
    //--->指针地址:0x100201a50, 引用计数:1

NSArray *array2 = [array copy];
for (NSObject *obj in array2) {
    NSLog(@"指针地址:%p, 引用计数:%ld",obj,obj.retainCount);
}   //--->指针地址:0x100202ad0, 引用计数:2
    //--->指针地址:0x100201a40, 引用计数:2
    //--->指针地址:0x100201a50, 引用计数:2
[array2 release];

3.对象的自定义拷贝

  1. 对象拥有的复制特性,必须实现NSCopying,NSMutableCopying协议,实现该协议的copyWithZone:方法和mutableCopyWithZone:方法.
  2. OC对象的深浅拷贝的区别在于我们对copyWithZone的不同实现.
    main.m文件
Person *person1 = [[Person alloc] init];
person1.name = [NSMutableString stringWithString:@"jack"];
person1.age = @20;
Person *person2 = [person1 copy];

***1.浅拷贝结果***
NSLog(@"person1第地址:%p,person2的地址:%p",person1,person2);
//-->person1第地址:0x100202790,person2的地址:0x100202a10-->拷贝出来的是两个对象
NSLog(@"name1的地址:%p,name2地址:%p",person1.name,person2.name);
//-->name1的地址:0x100202d90,name2地址:0x100202d90-->浅拷贝
NSLog(@"age1的地址:%p,age2地址:%p",person1.age,person2.age);
//-->age1的地址:0x1427,age2地址:0x1427-->浅拷贝

***2.深拷贝结果***
NSLog(@"person1第地址:%p,person2的地址:%p",person1,person2);
//-->person1第地址:0x1002032c0,person2的地址:0x100200d40-->拷贝出来的是两个对象
NSLog(@"name1的地址:%p,name2地址:%p",person1.name,person2.name);
//-->name1的地址:0x100202a10,name2地址:0x1002045e0-->深拷贝
NSLog(@"age1的地址:%p,age2地址:%p",person1.age,person2.age);
//-->age1的地址:0x1427,age2地址:0x1427-->浅拷贝

//copy不可变对象等效于retain
NSArray *array1 = [[NSArray alloc] initWithObjects:@"ttt", nil];
NSArray *array2 = [array1 copy];//=>>[array1 retain]
NSLog(@"array1指针:%p, array2指针:%p",array1,array2);
//--->array1指针:0x1001099d0, array2指针:0x1001099d0
NSLog(@"array1引用计数:%ld, array2引用计数:%ld",array1.retainCount,array2.retainCount);
//--->array1引用计数:2, array2引用计数:2  -->同一个对象

NSMutableString *s = [NSMutableString stringWithString:@"xxx"];
NSString *s2 = [s copy];
NSLog(@"s指针:%p, s2指针:%p",s,s2);
//--->s指针:0x10010b6c0, s2指针:0x100109950  -->不同地址
NSLog(@"s引用计数:%ld, s2引用计数:%ld",s.retainCount,s2.retainCount);
//--->s引用计数:1, s2引用计数:1  -->两个对象

Person.h文件

#import <Foundation/Foundation.h>
@interface Person : NSObject<NSCopying>

@property(nonatomic,copy)NSMutableString *name;
@property(nonatomic,retain)NSNumber *age;

@end

Person.m文件

#import "Person.h"
@implementation Person
- (id)copyWithZone:(NSZone *)zone {
***1.浅拷贝***
//Person *person = [[[self class] allocWithZone:zone] init];
//person.name = self.name;
//person.age = self.age;
//return person;

//***2.深拷贝***
Person *person = [[[self class] allocWithZone:zone] init];
//NSMutableString *name = [_name copy];//此方法也是浅拷贝,结果和上面的结果一样
NSMutableString *name = [_name mutableCopy];
NSNumber *age = [_age copy];//_age不支持mutableCopy,因为它没有可变的对象
person.name = name;
person.age = age;
[name release];
[age release];
return person;    
}
@end

4. 深浅拷贝和retain之间的总结

  1. :即copy,mutableCopy和retain之间的关系
    1) Foundation可复制的对象,当我们copy是是一个不可变的对象是,它的作用相当于retain(cocoa做的内存优化)
    2) 当我们使用mutableCopy时,无论源对象是否可变,副本是可变的,并且实现的了真正意义上的拷贝
    3) 当我们copy的是一个可变的对象时,副本对象是不可变的,同样实现了真正意义上的拷贝
  2. NSInteger 是在栈区的,效率高,速度快,可以放在方法内部使用 , NSNumber是对象,在堆中的,自带了数值转换功能,效率差一些,方便KVC赋值
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值