浅拷贝和深拷贝
对象的(指针指向)内存地址
浅拷贝:
第一,拷贝了指向对象的指针,拷贝出来的对象的指针和原对象的指针指向同一块内存地址.
第二,几个对象共用一块内存,当内存被回收时候,指向这块内存的对象指针需要重新定义,不然会造成野指针错误.
深拷贝:
第一,拷贝对象的具体内容,开辟新的内存,内存地址自助分配.
第二,拷贝完成之后,内存中的值是一样的,但是内存地址不一样,2个对象之间相互不影响,也不相互干涉;
小结:用通俗话来讲,
浅拷贝就是一个人和他的影子,本体被销毁了,那么影子也不存在;
深拷贝就好比一个人和他的克隆人,本体被销毁了,克隆人依然存在;
额外知识:
野指针:当前对象指针指向的内存已经被回收,但是依然有其他对象的指针指向这块内存,那么指向这块内存的对象指针就是野指针;
内存泄漏:申请内存没有释放,造成内存越来越少;常见是block,delegate,NSTimer的使用不当造成的循环引用;
注意:要实现浅拷贝和深拷贝的类必须遵循NSCopying,NSMutableCopying这2个协议,他们分别实现了以下2个协议的方法;
1 | @protocol NSCopying |
验证例子
copy,mutableCopy
第一,区分拷贝之后返回的对象是可变还是不可变;
第二,区分是深拷贝还是浅拷贝;
非容器类:NSString,NSMutableString
NSString
1 | NSString *str = @"123"; |
小结1.1:不可变字符串NSString:copy是浅拷贝,返回不可变字符串;mutableCopy是深拷贝,返回类型可变字符串;
NSMutableString
1 | NSMutableString *muStr = [[NSMutableString alloc]initWithString:@"123"]; |
小结1.2:可变字符串NSMutableString:copy和mutabCopy都是深拷贝,copy返回对象是不可变对象,mutableCopy返回的对象是可变对象;
copy返回的对象类型都是不可变类型,mutableCopy返回的类型都是可变类型,无论被拷贝的对象是可变还是不可变;
mutbalCopy都是深拷贝;
copy当被拷贝对象是不可变时候,是浅拷贝;当被拷贝的对象是可变时,是深拷贝;
容器类:NSArray,NSMutableArray
copy返回的对象类型都是不可变,被拷贝的对象是不可变时,依然是浅拷贝;被拷贝的对象是可变时,是深拷贝;
mutableCopy返回对象都是都是可变类型的,并且都是深拷贝;
NSArray
1 | NSArray *arr = @[@"321"]; |
NSMutableArray
1 | NSMutableArray *muArr = [[NSMutableArray alloc]initWithObjects:@"231", nil]; |
小结2.1:集合类深拷贝,虽然开辟了新的内存空间,但集合里面的值的内存还是指向相同的内存(指针拷贝),这叫单层深复制;
容器类实现完全深拷贝
使用归档:
1 | NSMutableArray *muA = [[NSMutableArray alloc]init]; |
小结3.1:可以看出经过归档和解档之后,容器类内存地址和里面的值的内存地址和原来的不一样;
end