博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
关于深复制与浅复制
阅读量:5083 次
发布时间:2019-06-13

本文共 7619 字,大约阅读时间需要 25 分钟。

转自“红黑联盟”,网址:http://www.2cto.com/kf/201405/302273.html

 

第一、复制对象的基本概念

复制一个对象为副本,开辟一块新的内存来存储副本对象。

第二、如果一个对象想具备复制的功能,必须实现协议和协议

NSObject自带的常用的对象有:NSNumber、NSString、NSArray、NSDictionary、NSMutableArray、NSMutableDictionay、NSMutableString,copy产生的对象时不可变的,mutableCopy产生的对象时可变的

第三、retain和copy的区别

 

@autoreleasepool {        NSMutableArray *array=[NSMutableArray arrayWithObjects:@"one",@"two",@"three",@"four",nil];        NSMutableArray *retainArray=[array retain];        [retainArray removeLastObject];        for(NSString *str in array)        {            NSLog(@"the part is %@",str);        }        NSLog(@"the retaincount is %ld",[retainArray retainCount]);        // insert code here...        NSLog(@"Hello, World!");            }

结果:

 

2014-05-19 10:58:22.639 objective[1095:303] the part is one2014-05-19 10:58:22.641 objective[1095:303] the part is two2014-05-19 10:58:22.641 objective[1095:303] the part is three2014-05-19 10:58:22.641 objective[1095:303] the retaincount is 2

 

 

NSMutableArray *array=[NSMutableArray arrayWithObjects:@"one",@"two",@"three",@"four",nil];        NSMutableArray *retainArray=[array mutableCopy];        [retainArray removeLastObject];        for(NSString *str in array)        {            NSLog(@"the part is %@",str);        }        NSLog(@"the retaincount is %ld",[retainArray retainCount]);

 

结果

2014-05-19 10:59:03.826 objective[1104:303] the part is one

2014-05-19 10:59:03.828 objective[1104:303] the part is two

2014-05-19 10:59:03.828 objective[1104:303] the part is three

2014-05-19 10:59:03.829 objective[1104:303] the part is four

2014-05-19 10:59:03.829 objective[1104:303] the retaincount is 1

 

第四、COPY和MutableCopy的区别

COPY 返回一个不可变对象的副本,MutalbeCopy返回一个可变对象的副本。

 

NSArray *array=[NSArray arrayWithObjects:@"one",@"two", nil];        NSMutableArray *array1=[array copy];        [array1 addObject:@"three"];  //error        NSMutableArray *array2=[array mutableCopy];        [array2 addObject:@"three"];  //right        // insert code here...        NSLog(@"Hello, World!");

第五、浅copy和深copy

 

浅复制尽复制对象本身,对象里的属性、包含的对象不做复制

深复制复制全部,包括对象的属性和其他对象

Foundation框架支持复制的类,默认是浅复制

 

NSMutableArray *array=[[NSMutableArray alloc] init];        for(int i=0;i<3;i++)        {            NSObject *obj=[[NSObject alloc] init];            [array addObject:obj];            [obj release];        }        for(NSObject *obj1 in array)        {            NSLog(@"地址为 %p,引用计数是 %ld",obj1,obj1.retainCount);        }        NSMutableArray *array2=[array copy];        for(NSObject *obj2 in array2)        {            NSLog(@"地址为 %p,引用计数是 %ld",obj2,obj2.retainCount);        }

 

2013-09-30 17:28:01.492 FDAS[681:303] 地址为 0x1001081f0,引用计数是 12013-09-30 17:28:01.506 FDAS[681:303] 地址为 0x100108230,引用计数是 12013-09-30 17:28:01.506 FDAS[681:303] 地址为 0x100108240,引用计数是 12013-09-30 17:28:01.507 FDAS[681:303] 地址为 0x1001081f0,引用计数是 22013-09-30 17:28:01.507 FDAS[681:303] 地址为 0x100108230,引用计数是 22013-09-30 17:28:01.507 FDAS[681:303] 地址为 0x100108240,引用计数是 2

第五、对象的自定义拷贝

对象拥有复制特性,必须实现NSCopying,NSMutableCopying协议,实现该协议的copyWithZone方法和mutableCopyWithZone方法

深拷贝和浅拷贝的区别就在于copyWithZone方法的实现,

浅拷贝代码如下:

 

#import @interface Person : NSObject@property(nonatomic,retain)NSString *name;@property(nonatomic,retain)NSString *age;@end

 

#import "Person.h"@implementation Person- (id)copyWithZone:(NSZone *)zone{   //实现自定义浅拷贝    Person *person=[[self class] allocWithZone:zone];    person.age=_age;    person.name=_name;    return person;}@end

main函数为:

@autoreleasepool {                Person *person=[[Person alloc] init];        person.name=@"andy";        person.age=@"20";                Person *person2=[person copy];        NSLog(@"person 地址为%p,person2地址为%p",person.name,person2.name);    }

输出结果为:

 

 

2013-09-30 17:48:41.007 FDAS[732:303] person 地址为0x1000022c8,person2地址为0x1000022c8

深拷贝代码如下:

 

 

 

- (id)copyWithZone:(NSZone *)zone{   //实现自定义浅拷贝    Person *person=[[self class] allocWithZone:zone];    person.age=[_age copy];    person.name=[_age copy];    return person;}

 

结果:

 

2013-09-30 17:55:13.603 FDAS[742:303] person 地址为0x1000022c8,person2地址为0x1000022e8

 

NSArray *arr=[NSArray arrayWithObjects:@"one",@"two",nil];        NSArray *arr2=[arr copy];        NSLog(@"the dress of arr is %p the dress of arr2 is %p",arr,arr2);        NSLog(@"the retainCount is %ld",arr.retainCount);

执行结果为:

 

 

2013-09-30 18:01:01.394 FDAS[787:303] the dress of arr is 0x100108320 the dress of arr2 is 0x100108320

2013-09-30 18:01:01.396 FDAS[787:303] the retainCount is 2

 

结果是一样的,是因为Foundation对于不可变复制对象而言,copy方法做了优化,相当于retain,故retaincount变成2.

相当于 在copyWithZone方法中:return [self retain];

第六、copy、mutableCopy和retain之间的关系

在Foundation对象中,copy是一个不可变的对象时,作用相当于retain

当使用mutableCopy时,不管源对象是否可变,副本是可变的,并且实现真正意义上的copy

当我们使用copy一个可变对象时,副本对象是不可变的。

关于深拷贝和浅拷贝:

第一、浅拷贝:

 

Car *car=[[[self class] allocWithZone:zone] init];    car.engine=_engine;    car.name=_name;    car.weight=_weight;    return car;

 

 

测试代码:

 

Car *car = [[Car alloc] init];        Engine *engine = [[Engine alloc] init];        car.engine = engine;        [engine release];        //NSLog(@"engine retaincount is %lu",[engine retainCount]);        car.name = @"奥迪";        car.weight = @1000;        Car *car2=[car copy];       // NSLog(@"car2 retaincount is %lu",[car2 retainCount]);        NSLog(@"car %@,car2:%@",car.engine,car2.engine);

输出结果:

 

 

car ,car2:

可以看出浅复制只是复制指针,并没有创建新的内存空间

第二、深拷贝:

 

- (id)copyWithZone:(NSZone *)zone {    /***浅拷贝**/    Car *car=[[[self class] allocWithZone:zone] init];    Engine *engineCopy=[[_engine copy] autorelease];    car.engine=engineCopy;        NSString *namecopy=[[_name copy] autorelease];    car.name=namecopy;        NSNumber *weightcopy=[[_weight copy] autorelease];    car.weight=weightcopy;    return car;}

测试代码:

 

 

Car *car = [[Car alloc] init];        Engine *engine = [[Engine alloc] init];        car.engine = engine;        [engine release];        //NSLog(@"engine retaincount is %lu",[engine retainCount]);        car.name = @"奥迪";        car.weight = @1000;        Car *car2=[car copy];       // NSLog(@"car2 retaincount is %lu",[car2 retainCount]);        NSLog(@"car %@,car2:%@",car.engine,car2.engine);

结果:

 

 

car ,car2:

开辟了新的空间,zone代表一块内存空间

 

Car *car=[[[self class] allocWithZone:zone] init];

 

注意上述代码用的是【self class】,而不是car,因为如果是用car,那么car的子类在调用此方法去实现copy协议时,就会出现内存问题

 

另外,当子类继承了父类时,他继承了父类的一切属性,包括要实现的协议

第三、NSFoundation,当我们copy的时一个不可变对象时,默认的copy都是浅拷贝,相当于retain

 

NSArray *array =[NSArray arrayWithObjects:@"one",@"two",@"three", nil];        NSArray *array1 = [array copy];        NSLog(@"%p",array);        NSLog(@"%p",array1);        NSLog(@"the retaincount is %lu",[array retainCount]);

输出结果:

 

 

 

copyDemo1[673:303] 0x10010a5d0

2013-12-28 20:01:10.969 copyDemo1[673:303] 0x10010a5d0

2013-12-28 20:01:10.969 copyDemo1[673:303] the retaincount is 2

注意retaincount会增加

当使用mutableCopy时,不管对象是否可变,都会实现深拷贝

 

NSArray *array =[NSArray arrayWithObjects:@"one",@"two",@"three", nil];        NSMutableArray *array1 = [array mutableCopy];        NSLog(@"%p",array);        NSLog(@"%p",array1);        NSLog(@"the retaincount is %lu",[array retainCount]);

结果:

 

 

copyDemo1[695:303] 0x10010a5d0

2013-12-28 20:07:08.570 copyDemo1[695:303] 0x10010b260

2013-12-28 20:07:08.570 copyDemo1[695:303] the retaincount is 1

第四、retain相当于两个对象指向同一个指针

 

NSMutableArray *array1 = [[NSMutableArray alloc] initWithObjects:@"one",@"two",@"three",@"foure", nil];        NSMutableArray *array2 = [array1 retain];        [array2 removeLastObject];        NSLog(@"%@",array1);        NSLog(@"the retaincount is %ld",array2.retainCount);

结果:

 

 

2013-12-28 20:13:02.915 copyDemo1[736:303] (    one,    two,    three)2013-12-28 20:13:02.917 copyDemo1[736:303] the retaincount is 2

转载于:https://www.cnblogs.com/jyq-blog/p/4492111.html

你可能感兴趣的文章
http://lorempixel.com/ 可以快速产生假图
查看>>
编写一个函数isMerge,判断一个字符串str是否可以由其他两个字符串part1和part2“组合”而成...
查看>>
一个自己写的判断2个相同对象的属性值差异的工具类
查看>>
oracle连接的三个配置文件(转)
查看>>
Python内置函数(29)——help
查看>>
Android TextView加上阴影效果
查看>>
《梦断代码》读书笔记(三)
查看>>
AngularJS学习篇(一)
查看>>
关于Xshell无法连接centos6.4的问题
查看>>
spring security 11种过滤器介绍
查看>>
代码实现导航栏分割线
查看>>
大数据学习系列(8)-- WordCount+Block+Split+Shuffle+Map+Reduce技术详解
查看>>
Mysql性能调优
查看>>
ES6内置方法find 和 filter的区别在哪
查看>>
Android实现 ScrollView + ListView无滚动条滚动
查看>>
硬件笔记之Thinkpad T470P更换2K屏幕
查看>>
getElement的几中属性介绍
查看>>
HTML列表,表格与媒体元素
查看>>
设计器 和后台代码的转换 快捷键
查看>>
STL容器之vector
查看>>