Objective-C 谈谈深浅拷贝,copy和mutable copy都不是完全拷贝
(一)字符串中的指针赋值,copy和mutablecopy
NSString和NSString
(1)指针赋值
肯定指向同一个字符串地址。
(2)copy(和直接指向一样)

NSString *str1=@"aaa";
NSString *str2=[str1 copy];
NSLog(@"str1:%p----str2:%p",&str1,&str2);//指针地址输出,不一样,说明指针新建了
NSLog(@"str1:%p----str2:%p",str1,str2);//指针指向内容地址输出,是一样的,说明内容没有被拷贝
结果说明Copy也没实现拷贝,说明以下情况都是等价的,都指向同个内存区域
NSString *str2=str1;
NSString *str3 = [[NSString alloc]initWithString:str1];
NSString *str4 = [NSString stringWithString:str1];
NSString *str5 = [str1 copy];
如果场景需要,比如为了让某个str1指向的地方销毁,要先拷贝到新地址,然后用str2指,可以对NSString进行拷贝。
(3)mutablecopy(实现了拷贝)

NSString *str1=@"aaa";
NSString *str2=[str1 mutableCopy];
NSLog(@"str1:%p----str2:%p",&str1,&str2);//指针地址输出,不一样,说明指针新建了
NSLog(@"str1:%p----str2:%p",str1,str2);//指针指向内容地址输出,是不一样的,说明重新开辟了内存,把str1的内容拷贝到新内存,str2变量指向这个新地址
NSMutableString到NSMutableString
(1)指针赋值:
肯定指向同一个可变字符串地址。
(2)mutablecopy

NSMutableString *mStr=[NSMutableString stringWithString:@"abc"];
NSMutableString *mStr2=[mStr mutableCopy];
NSLog(@"mstr:%p-----mstr2:%p",mStr,mStr2);//指针内容地址不一样,说明实现了拷贝
[mStr2 appendString:@"def"];
NSLog(@"mstr:%@-----mstr2:%@",mStr,mStr2);//互不相干
此种方式实现了对NSMutableString的拷贝,产生两个互不相干的可变字符串。
(3)copy( 错误,会崩)
NSMutableString *mStr2=[mStr copy];
NSMutableString到NSString
(1)指针赋值:
NSMutableString *mStr=[NSMutableString stringWithString:@"abc"];
NSString *str=mStr;
NSLog(@"mstr:%p-----str:%p",mStr,str);//指针指向内容地址一样,说明mStr的改变会联动str
[mStr appendString:@"def"];
NSLog(@"mstr:%@-----str:%@",mStr,str);//mStr的改变影响了str
这种情况,mStr的改变会影响str,但str改变就会重新指向,并不会影响mStr
(2)copy和mutablecopy:
NSMutableString *mStr=[NSMutableString stringWithString:@"abc"];
NSString *str=[mStr copy];//NSString *str=[mStr mutableCopy];也能实现
NSLog(@"mstr:%p-----str:%p",mStr,str);
这种情况,str对mStr进行拷贝,mStr改变不影响str。
但这里面,[mStr copy]和[mstr mutableCopy],虽然都对原mStr进行了拷贝,开辟了新内存区域,但区别在于前者拷贝的对象是不可变的,后者的是可变的。可变字符串赋值给NSString其实也就丧失动态性了。
NSString到NSMutableString
用copy方法,让NSString给NSMutableString赋值的也是作死行为,应该使用StringWithString方法初始化NSMutableString
NSString *str1=@"str1";
NSMutableString *mStr=[str1 copy];
[mStr appendFormat:@"abc"];
总结一下:
1.NSString之间,copy并不能实现拷贝(等同直接指向),必须mutablecopy实现拷贝
2.NSMutableString之间,Mutablecopy实现拷贝。
3.对于NSMutableString拷贝给NSString,copy和mutablecopy都能完成任务。
所以:对于字符串之间的拷贝,必须Mutablecopy才能实现拷贝。
数组变量赋值时的直接指向,copy和mutablecopy
NSArray和NSArray
(1)直接指向
肯定是指向同个数组。
(2)copy

NSArray *array1=[NSArray arrayWithObjects:@"1",@"2",@"3",nil];
NSArray *array2=[array1 copy];
NSLog(@"arr1:%p,arr2:%p",&array1,&array2);//指针地址不同,说明是2个不一样的指针变量
NSLog(@"arr1:%p,arr2:%p",array1,array2);//数组指针指向内容相同,说明copy方法对NSArray而言,依旧是直接指向,并无拷贝
NSLog(@"arr1:%p,arr2:%p",array1[0],array2[0]);//数组地址相同,内容地址肯定相同了
说明copy也没实现拷贝,依旧指向同个数组。
(3)mutablecopy

NSArray *array1=[NSArray arrayWithObjects:@"1",@"2",@"3",nil];
NSArray *array2=[array1 mutableCopy];
NSLog(@"arr1:%p,arr2:%p",&array1,&array2);//不同指针变量,地址不同
NSLog(@"arr1:%p,arr2:%p",array1,array2);//数组地址不同,说明数组实现了拷贝
NSLog(@"arr1:%p,arr2:%p",array1[0],array2[0]);//元素地址相同,说明元素并没有被拷贝
说明实现了拷贝,但数组内元素的指针被拷贝,但元素并没有被拷贝。
NSMutableArray和NSMutableArray
(1)直接指向
同一个嘛。肯定一起改。
(2)mutablecopy

NSMutableArray *mArray1=[NSMutableArray arrayWithObjects:
[NSMutableString stringWithString:@"1"],
[NSMutableString stringWithString:@"2"],
[NSMutableString stringWithString:@"3"],nil];
NSMutableArray *mArray2=[mArray1 mutableCopy];
NSLog(@"arr1:%p,arr2:%p",&mArray1,&mArray2);//指针地址不同,说明是2个不一样的指针
NSLog(@"arr1:%p,arr2:%p",mArray1,mArray2);//数组地址不同,说明数组得到了拷贝
NSLog(@"arr1:%p,arr2:%p",mArray1[0],mArray2[0]);//内容地址相同,说明内容并没有拷贝
说明mutablecopy实现了拷贝,但没有实现数组内部元素的拷贝。
这种内容为可变元素的情况下,如果对可变数组1元素改变,可变数组2元素也会一起改。并没有实现完全拷贝。要实现完全拷贝,就要继续一层层剥开,全部拷贝再重组数组。
说明:
1.和NSString一样,NSArray的copy方法其实都没有实现一丁点拷贝(和直接指向是一样的),只有Mutablecopy才能实现拷贝。
2.但mutablecopy只是拷贝了数组本身和数组中每个元素的指针,并没有实现数组元素的拷贝。
自定义类实现NSCopying和NSMutableCopying协议
如果没有实现这两个协议,copy和mutablecopy方法都是不会得到响应的,并且具体拷贝的程度,也和具体实现有关
新建Student类
.h
#import <Foundation/Foundation.h> @interface Student : NSObject<NSCopying,NSMutableCopying> @property (copy) NSString *name;
@property (copy) NSString *age;
@property (strong) NSMutableArray *GradeArray;
@end
.m
#import "Student.h"
@implementation Student
-(id)initWithName:(NSString *)name GradeArray:(NSMutableArray *)gradeArray{
self=[super init];
if (self) {
self.name=name;
self.GradeArray=gradeArray;
}
return self;
}
-(id)copyWithZone:(NSZone *)zone
{
Student *stu = [[Student allocWithZone:zone] initWithName:self.name GradeArray:self.GradeArray];
return stu;
}
-(id)mutableCopyWithZone:(NSZone *)zone{
Student *stu = [[Student allocWithZone:zone] initWithName:self.name GradeArray:self.GradeArray];
return stu;
}
@end
copy:
Student *stu1=[[Student alloc]init];
stu1.name=@"stu1";
stu1.GradeArray=[[NSMutableArray alloc]init];
[stu1.GradeArray addObject:@"100"];
Student *stu2=[stu1 mutableCopy];
NSLog(@"stu1:%p----stu2:%p",stu1,stu2);//stu1:0x7faa43c1b050----stu2:0x7faa43c1d0d0
NSLog(@"stu1:%p----stu2:%p",stu1.name,stu2.name);//stu1:0x10df5f080----stu2:0x10df5f080
NSLog(@"stu1:%p----stu2:%p",stu1.GradeArray,stu2.GradeArray);//stu1:0x7faa43c1ad40----stu2:0x7faa43c1ad40
说明对象拷贝了,但成员的指针所指内容并没有拷贝。
对于自定义对象,最深的拷贝也只能到拷贝成员指针的程度了,说明copy和mutablecopy都不是完全拷贝
总结下,如果要对某个对象实现完全拷贝:
1.必须分别对Class里的每个对象进行mutablecopy(对于基本数据对象,copy不一定行哦)
2.并且如果Class里存在容器性质的对象(比如Array和MutableArray),目前只是拷贝了该数组,没有拷贝可变数组里的元素所指内容,要完全拷贝得再深挖进去,对该mutableArray的每个元素进行mutablecopy
直到对非容器性质的对象进行mutablecopy后才算完全拷贝
Student *stu1=[[Student alloc]init];
stu1.name=@"stu1";
stu1.GradeArray=[[NSMutableArray alloc]init];
[stu1.GradeArray addObject:@"100"];
Student *stu2=[stu1 mutableCopy];
stu2.name=[stu1.name mutableCopy];
stu2.GradeArray=[stu1.GradeArray mutableCopy];
NSLog(@"stu1:%p----stu2:%p",stu1,stu2);//stu1:0x7faa43c1b050----stu2:0x7faa43c1d0d0
NSLog(@"stu1:%p----stu2:%p",stu1.name,stu2.name);//stu1:0x10df5f080----stu2:0x10df5f080
NSLog(@"stu1:%p----stu2:%p",stu1.GradeArray,stu2.GradeArray);//stu1:0x7faa43c1ad40----stu2:0x7faa43c1ad40
所以一个比较好的方法就是像上个博客里面说的,遵循NSCoding协议,先归档(序列化),再解开(反序列化)
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:stu1];
Student *stu2 = [NSKeyedUnarchiver unarchiveObjectWithData:data];
啊完全拷贝啊~~一切都清净了。。。
Objective-C 谈谈深浅拷贝,copy和mutable copy都不是完全拷贝的更多相关文章
- 复制对象 copy 与mutable copy
转载 : http://blog.csdn.net/u010962810/article/details/18887841 通过copy方法可以创建可变对象或不可变对象的不可变副本,对于不可 ...
- (五)聊一聊深Copy与浅Copy
一.关于浅copy与深copy 首先说明一下: 在python中,赋值其实就是对象的引用,变量就是对象的一个标签,如果把内存对象比喻成一个个房间,那么变量就是门牌号. 深copy与浅copy只是针对可 ...
- copy&mutableCopy 浅拷贝(shallow copy)深拷贝 (deep copy)
写在前面 其实看了这么多,总结一个结论: 拷贝的初衷的目的就是为了:修改原来的对象不能影响到拷贝出来得对象 && 修改拷贝出来的对象也不能影响到原来的对象 所以,如果原来对象就是imm ...
- Shallow copy and Deep copy
Shallow copy and Deep copy 第一部分: 一.来自wikipidia的解释: Shallow copy One method of copying an object is t ...
- python deep copy and shallow copy
Python中对于对象的赋值都是引用,而不是拷贝对象(Assignment statements in Python do not copy objects, they create bindings ...
- [CareerCup] 13.4 Depp Copy and Shallow Copy 深拷贝和浅拷贝
13.4 What is the difference between deep copy and shallow copy? Explain how you would use each. 这道题问 ...
- C/C++深度copy和浅copy
#define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<stdlib.h> #include<string. ...
- Python的深copy和浅copy
浅拷贝(copy):拷贝父对象,不会拷贝对象的内部的子对象. 深拷贝(deepcopy): copy 模块的 deepcopy 方法,完全拷贝了父对象及其子对象. 浅copy: a = [1, 2, ...
- Python学习-赋值、浅copy和深copy
Python Copy: 在Python语言中,分为浅拷贝和深拷贝两种形式,也就是官方文档中的Shadow copy和Deep copy.在对简单的对象(object)进行复制时,两者没有区别,如下面 ...
随机推荐
- codevs3143 二叉树的序遍历
难度等级:白银 3143 二叉树的序遍历 题目描述 Description 求一棵二叉树的前序遍历,中序遍历和后序遍历 输入描述 Input Description 第一行一个整数n,表示这棵树的节点 ...
- UDP的坏处
众所周知,UDP是一个面向无连接的协议.通信时不可靠的.这就会出现一些问题 (1)数据报丢失 因为是无连接,的所以可以用recvfrom和sendto来接收和发送消息,如果socket是阻塞的,那么当 ...
- java调用.net asmx / wcf
一.先用asmx与wcf写二个.net web service: 1.1 asmx web服务:asmx-service.asmx.cs using System; using System.Coll ...
- 我的第一个 JSP (SSH) 个人网站【开源】
唠叨两句背景 相当长时间没上来发帖了,最近几个月除了完成产品经理一个又一个重复又重复的app开发任务之外,最大的工作莫过于充分利用上笔主的业余时间,系统性地跟李刚同志学习JavaEE的SSH框架开发技 ...
- 使用HttpWebRequest和HtmlAgilityPack抓取网页(拒绝乱码,拒绝正则表达式)
废话不多说, 直接说需求. 公司的网站需要抓取其他网站的文章,但任务没到我这,同事搞了一下午没搞出来.由于刚刚到公司, 想证明下自己,就把活揽过来了.因为以前做过,觉得应该很简单,但当我开始做的时候, ...
- Congruence relation 同余关系
https://en.wikipedia.org/wiki/Congruence_relation https://zh.wikipedia.org/wiki/%E5%90%8C%E9%A4%98%E ...
- Graphql介绍(Introduction to GraphQL)
Introduction to GraphQL GraphQL介绍 Learn about GraphQL, how it works, and how to use it in this seri ...
- yii2组件之下拉框带搜索功能(yii-select2)
简单的小功能,但是用起来还是蛮爽的.分享出来让更多的人有更快的开发效率,开开心心快乐编程. 如果你还没有使用过composer,你可就out了,看我的教程分享,composer简直就是必备神奇有木有. ...
- 【心得】在脱离TFS的情况下,如何解除TFS绑定?
我们知道在有TFS的情况下,在文件-源代码管理-高级中可以解除TFS绑定. 但是如果我们出差去了,拿着笔记本电脑,打开解决方案的时候,会总是提示无法连接TFS,并且在源代码管理处尝试解除的时候也提示无 ...
- selector 和 shape结合使用
<?xml version="1.0" encoding="utf-8"?><selector xmlns:android="htt ...