copy深拷贝和浅拷贝的理解和使用
来源:互联网 发布:发票抵扣网络认证系统 编辑:程序博客网 时间:2024/04/30 04:55
概念:
复制一个对象为副本,开辟一块新的内存来存储副本对象。
如果一个对象想具备复制的功能,必须实现协议和协议
1 深复制:内容拷贝,源对象和副本对象指的是两个不同的对象,源对象引用计数器不变,副本对象引用计数器为1
2 浅复制:指针拷贝,源对象和副本对象指的都是同一个对象,对象引用计数器+1,相当于retain
3 只有不可变对象创建不可变副本(copy)才是浅复制,其它的都是深复制
4.ios中哪些可变哪些不可变:
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 one
2014
-
05
-
19
10
:
58
:
22.641
objective[
1095
:
303
] the part is two
2014
-
05
-
19
10
:
58
:
22.641
objective[
1095
:
303
] the part is three
2014
-
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
,引用计数是
1
2013
-
09
-
30
17
:
28
:
01.506
FDAS[
681
:
303
] 地址为
0x100108230
,引用计数是
1
2013
-
09
-
30
17
:
28
:
01.506
FDAS[
681
:
303
] 地址为
0x100108240
,引用计数是
1
2013
-
09
-
30
17
:
28
:
01.507
FDAS[
681
:
303
] 地址为
0x1001081f0
,引用计数是
2
2013
-
09
-
30
17
:
28
:
01.507
FDAS[
681
:
303
] 地址为
0x100108230
,引用计数是
2
2013
-
09
-
30
17
:
28
:
01.507
FDAS[
681
:
303
] 地址为
0x100108240
,引用计数是
2
第五、对象的自定义拷贝
对象拥有复制特性,必须实现NSCopying,NSMutableCopying协议,实现该协议的copyWithZone方法和mutableCopyWithZone方法
深拷贝和浅拷贝的区别就在于copyWithZone方法的实现,
浅拷贝代码如下:
#
import
<foundation foundation.h=
""
>
@interface
Person : NSObject<nscopying>
@property
(nonatomic,retain)NSString *name;
@property
(nonatomic,retain)NSString *age;
@end
</nscopying></foundation>
#
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
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
- copy深拷贝和浅拷贝的理解和使用
- 深拷贝和浅拷贝的理解?
- 深拷贝和浅拷贝的理解
- 深拷贝和浅拷贝的理解?
- 深拷贝和浅拷贝的理解?
- 深拷贝和浅拷贝(copy)的区别
- 浅拷贝和深拷贝 iOS 的copy 以及 mutablecopy
- copy和mutableCopy的深、浅拷贝
- OC中关于copy和mutableCopy的使用 及深拷贝、浅拷贝的概念
- 浅拷贝和深拷贝(shallow copy VS deep copy )
- 浅拷贝、深拷贝 Bitwise Copy和Memberwise Copy
- 深拷贝、浅拷贝、memberwise copy 和 bitwise copy
- 浅拷贝、深拷贝以及Memberwise Copy 和 Bitwise Copy
- 浅拷贝、深拷贝 Bitwise Copy和Memberwise Copy
- 深拷贝和浅拷贝和copy和mutableCopy总结
- IOS 之copy(浅拷贝)和mutableCopy(深拷贝) 以及strong 和weak理解
- 深拷贝和浅拷贝(mutableCopy和Copy)详解
- retain和copy,深拷贝和浅拷贝
- vector的用法【转载】
- 工具类:SPUtil
- window.onload,body onload,document.onreadystatechange
- Jquery实际应用,判断radio,selelct,checkbox是否选中及选中的值
- Rotate Array
- copy深拷贝和浅拷贝的理解和使用
- iOS巅峰之UILabel上显示不同的字体样式和颜色
- 用Maven创建Spring3 MVC项目(转)
- PHP每日函数学习之 array_walk函数
- View学习笔记----View坐标
- JAVA基础知识回顾-----多线程基础-----随想随写
- leetcode 109. Convert Sorted List to Binary Search Tree-链表转树|指针|二分归并
- 继承Circle类
- linux下使用命令更改命令行终端提示符里面的主机名