黑马程序员--浅析浅复制和深复制的本质

@import url(http://i.cnblogs.com/Load.ashx?type=style&file=SyntaxHighlighter.css);@import url(/css/cuteeditor.css);

实例浅析oc中的浅复制和深复制的本质

代码段1:

#import <Foundation/Foundation.h>

int main(int argc, const char * argv[]) {

@autoreleasepool {

NSMutableArray *dataArray = [NSMutableArray arrayWithObjects:@"one",@"two",@"three",@"four", nil];

NSMutableArray *dataArray2;

// copy

dataArray2 = dataArray;

[dataArray2 removeObjectAtIndex:0];

NSLog(@"dataArray:");

for (NSString *elem in dataArray) {

NSLog(@"%@",elem);

}

NSLog(@"dataArray2: ");

for (NSString *elem in dataArray2) {

NSLog(@"%@",elem);

}

// mutableCopy

dataArray2 = [dataArray mutableCopy];

[dataArray2 removeObjectAtIndex:0];

NSLog(@"dataArray:");

for (NSString *elem in dataArray) {

NSLog(@"%@",elem);

}

NSLog(@"dataArray2: ");

for (NSString *elem in dataArray2) {

NSLog(@"%@",elem);

}

}

return 0;

}

 打印结果如下:

dataArray:

 two

 three

 four

 dataArray2: 

 two

 three

 four

 dataArray:

 two

 three

 four

 dataArray2: 

 three

 four

代码段2:

#import <Foundation/Foundation.h>

int main(int argc, const char * argv[]) {

@autoreleasepool {

NSMutableArray *dataArray = [NSMutableArray arrayWithObjects:

[NSMutableString stringWithString:@"1"],

[NSMutableString stringWithString:@"2"],

[NSMutableString stringWithString:@"3"],

[NSMutableString stringWithString:@"4"],

[NSMutableString stringWithString:@"5"],

[NSMutableString stringWithString:@"6"],

[NSMutableString stringWithString:@"7"],

nil];

NSMutableArray *dataArray2;

NSMutableString *mStr;

NSLog(@"dataArray :");

for (NSString *elem in dataArray) {

NSLog(@"%@",elem);

}

// 做一次拷贝,然后改变第一个字符串

dataArray2 = [dataArray mutableCopy];

mStr = [dataArray objectAtIndex:0];

[mStr appendString:@"oc"];

NSLog(@"dataArray :");

for (NSString *elem in dataArray) {

NSLog(@"%@",elem);

}

NSLog(@"dataArray2 :");

for (NSString *elem in dataArray2) {

NSLog(@"%@",elem);

}

}

return 0;

}

打印结果如下:

dataArray :

1

2

3

4

5

6

7

dataArray :

1oc

2

3

4

5

6

7

dataArray2 :

1oc

2

3

4

5

6

7

为了便于理解,我们可以把数组对象看成指针数组,dataArray这个指针是指向指针数组的指针,数组中的元素指针指向的是对象

分析:copy复制对象结果是dataArray和dataArray2指向同一个数组对象。

MutableCopy复制对象的结果是,创建数组对象的副本,即dataArray 和 dataArray2指向不同的对象,但是两个数组对象中的元素对应的指向的同一个对象  即dataArray[0] 和 dataArray[0]指向同一个对象,dataArray[1] 和 dataArray2[1]指向同一个对象

从内存的管理的角度去分析

copy的结果是数组对象的计数器加1,mutableCopy的结果是数组对象中的元素(对象)的计数器加1

代码段1:分析

copy只是复制数据对象的引用,数组对象本身发生改变,不管用哪个指针去访问,结果都相同

MutableCopy复制元素的引用,因为两个数据对象指针并没有指向同一个数组对象,所以dataArray2数组元素的个数改变并不影响dataArray

dataArray的元素依旧有指针指向@“two”这个字符串对象

代码段2:分析

mutableCopy创建了数据对象的副本,并把副本的地址传递给dataArray2。数组对象的元素对象计数器都加1。当我们改变了数组元素对象的内容的时候,由于两个数组对象的元素指针指向相同的对象,所以两个数组对象打印结果会相同

想要做到完全复制,我们就要一层一层的胃对象创建副本,知道最底层,这个怎么理解呢,就拿上面两段代码来说copy没有创建副本,mutableCopy创建了一层,我们只要再为数组对象元素,为这些字符串对象都创建副本,那我我们再怎么去改动dataArray 也不会影响到dataArray2

我们可以使用Foundation的归档能力创建对象的深复制。如下代码所示,dataArray归档到一个缓冲区,然后再把它解归档,将结果指派给dataArray2,从而将dataArray复制给dataArray。这个过程不需要使用文件。归档和解归档过程都可以在内存中发生。代码如下

#import <Foundation/Foundation.h>

int main(int argc, const char * argv[]) {

@autoreleasepool {

NSData *data;

NSMutableArray *dataArray = [NSMutableArray arrayWithObjects:

[NSMutableString stringWithString:@"1"],

[NSMutableString stringWithString:@"2"],

[NSMutableString stringWithString:@"3"],

[NSMutableString stringWithString:@"4"],

[NSMutableString stringWithString:@"5"],

[NSMutableString stringWithString:@"6"],

[NSMutableString stringWithString:@"7"],

nil];

NSMutableArray *dataArray2;

NSMutableString *mStr;

// 用archiver进行深复制

data = [NSKeyedArchiver archivedDataWithRootObject:dataArray];

dataArray2 = [NSKeyedUnarchiver unarchiveObjectWithData:data];

mStr = [dataArray2 objectAtIndex:1];

[mStr appendString:@"ios"];

NSLog(@"dataArray :");

for (id obj in dataArray) {

NSLog(@"%@",obj);

}

NSLog(@"dataArray2 :");

for (id obj in dataArray2) {

NSLog(@"%@",obj);

}

}

return 0;

}

dataArray :

1

2

3

4

5

6

7

dataArray2 :

1

2ios

3

4

5

6

7


@import url(http://i.cnblogs.com/Load.ashx?type=style&file=SyntaxHighlighter.css);@import url(/css/cuteeditor.css);

时间: 2024-08-05 15:19:49

黑马程序员--浅析浅复制和深复制的本质的相关文章

黑马程序员_浅谈out参数、ref参数和可变参数

1.out参数 out关键字会导致参数通过引用来传递,通俗点说,就是往外传值的. out参数的作用:用于以内部变量为外部变量赋值的,out一般适用于某个方法不只是使用return返回单个值,而是需要有多个返回值的情况. out参数的使用需要注意以下几点:  1)out参数传递的变量在传递之前不需要对其进行初始化. 分析:在调用方法之前,对out参数传递的变量只需声明,可以赋值也可以不赋值,不过反正都是要在调用时被覆盖掉,所以大可不必赋值,因为赋值了虽然不会报错,但却根本也没有用处,没必要多此一举

黑马程序员_IO流2

File类 1.File类 不属于流对象.作用:将机器上的路径和目录封装成一个File对象,提供了很多的方法和成员变量,让我们操作目录和路径   目录就是文件夹.路径,指由文件夹组成的到达文件夹的通道. 2.File类的静态成员变量   一共提供的4个变量,掌握的只有2个,跨平台 static String separator  结果\ Windows目录分隔符  Linux下 / static String pathSeparator 结果 ; Windows下的路径与路径之间的分隔符 Lin

黑马程序员——I/O流基础知识

I/O流 Io流 代表有能力产生数据的数据源对象或者有能力接收对象的数据接收端对象.字节流和字符流.中文字符也转编码表,jbk2万多中文字.unicode全世界的字符收录.乱码,两种不同形式的编码表.字符流里面的对象融合了编码表,以便别人使用的使用用你指定的编码方式. 基类:读和写~ 字节流 InputStream,OutputStream 字符流 Reader,Writer Writer 主力方法是writer().既然IO流是操作数据的,而数据的最常见体现形式是:文件. 需求:准备在硬盘上创

黑马程序员——Java I/O流基础知识点(File类)

File工具 File类就是用俩将文件或者文件夹封装对象,弥补流对象的不足--流只能操作数据,不能操作文件夹的 封装的是路径!!! 构造方法演示 1.可以将已有的未出现的文件或者文件夹封装成对象. File f1=new File("c:\\abc\\a.txt"): File f2=new File("d:\\abc","ab.txt"打印,会打印路径.:目录分隔符,为了更好地跨平台File. File类常见功能 1,创建 createNewF

黑马程序员——IO篇

------- android培训.java培训.期待与您交流! ---------- IO(Input Output)流 1.IO流用来处理设备之间的数据传输 2.Java对数据的操作是通过流的方式 3.Java用于操作流的对象都在IO包中 4.流按操作数据分为两种:字节流与字符流 . 字符流的数据字节流其实都能处理,因为无论什么在计算机上最后都是以字节存在的,但是其中有一部分数据它是以文本形式存在的,所以为了方便有了字符流,字符流里融合了编码表,而只有文字用到了编码表,所以字符流用来处理文本

JAVA浅复制与深复制

1.浅复制与深复制概念 ⑴浅复制(浅克隆)     多个变量指向一个对象    被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象.换言之,浅复制仅仅复制所考虑的对象,而不复制它所引用的对象. ⑵深复制(深克隆)     每个变量指向一个对象,同时对象内包含对象,能复制内部对象    被复制对象的所有变量都含有与原来的对象相同的值,除去那些引用其他对象的变量.那些引用其他对象的变量将指向被复制过的新对象,而不再是原有的那些被引用的对象.换言之,深复制把要复

(转)黑马程序员 ---- 博客格式

<a href="http://www.itheima.com"target="blank">ASP.Net+Unity开发</a>.<a href="http://www.itheima.com"target="blank">.Net培训</a>.期待与您交流! 1.每篇日记标题前必须加上“黑马程序员”. 2.请将以下代码复制到每篇日记开始处. ----------------

黑马程序员_IO流1

异常1.异常的继承体系: java.lang.Throwable类,所有异常和错误的父类 Error类所有错误的父类 Exception类所有异常的父类 RuntimeException NullPointerException ClassCastException IndexOutOfBoundsException 错误,比较严重的问题,一旦出现了错误,程序根本不能运行,必须修改源代码. 异常,比较轻微的问题,一旦出现了异常,程序可以处理掉异常,继续运行.异常一般是程序的最后一个问题. 2.T

黑马程序员——Java I/O基础知识之I/O流

I/O流基础知识--字节流和字符流 文件存储在硬盘中,是以二进制表示的,只有内存中才能形成字符.数据的来源可以有硬盘,内存,控制台,网络,Java把数据从一个地方转到另一个地方的现象称为流,用InputStream和OutputStream接口来表示,这两个流里面的都是以字节为单位的,后来加入了Reader和Writer,里面操作的是字符,是两个字节为单位的. 字节流 字节流将数据写入文件 try { File file =new File("d:" +File .separator+