iOS之深拷贝与浅拷贝

在最开始,我们需要清楚一些关于内存分配方式的基础知识。

一般来说分为栈、堆、静态变量存储区、全局变量存储区、代码区。

前两个大家都懂的。通常将后三个合并称之为静态存储区,存储的是一些全局变量、静态变量、常量、执行代码等。

在Objective-C中,不可变数组、不可变字典以及一些常量字符串,都是分配在这个区域的,我们先要明确这一点。

所以在提到深浅拷贝的时候,用NSArray举例子的,只能说对内存分配方式就不清楚,因为对一个不可变数组进行copy操作,它实际上返回的是一个对象,跟深浅拷贝无关,因为都是按照retain来处理的。这也就是很多所谓教程提到的指针拷贝。

下面先说一下可变拷贝和不可变拷贝,分别遵循NSCopying和NSMutableCopying协议,需要对应实现copyWithZone:方法和mutableCopyWithZone:方法。

分两种情况来讲,一种是系统容器类,一种是自定义类。

一、系统容器类。

例如NSArray、NSDictionary,它们已经实现了上面两个协议。

对于它们来说,规则很简单,obj2 = [obj1 copy]返回的必然是一个不可变对象,无论obj1是可变对象还是不可变对象。如果obj1是一个不可变对象,那么它们指向同一个对象,也是上一条我提到过的。

obj2 = [obj1 mutableCopy]返回的必然是一个可变对象,无论obj1是可变对象还是不可变对象。即使obj1也是一个可变对象,它们仍指向不同地址,是两个对象。

二、自定义类。

因为copyWithZone:和mutableCopyWithZone:完全由自己来实现,所以代码的不同实现方式,决定了返回对象是什么。

在demo中Element类的copyWithZone:有注释,感兴趣的可以参考一下。

极端一点的例子,例如你直接在copyWithZone:方法中return self;那么obj2 = [obj1 copy]相当于obj2 = obj1,只是一个assign,没有做任何其它操作。

下面着重说一下浅拷贝和深拷贝。

首先顾名思义,无论是浅拷贝还是深拷贝,都有一个拷贝在里面,那些说浅拷贝相当于retain、什么所谓指针拷贝的,建议还是不要误人子弟了好吧。

这里我们以NSMutableArray为例

NSMutableArray *element = [NSMutableArray arrayWithObject:@1];

NSMutableArray *array = [NSMutableArray arrayWithObject:element];

id mutableCopyArray = [array mutableCopy];

这一句代码就是浅拷贝,是拷贝了容器自身,返回了一个新的可变数组,指向不同的内存地址。

内部的元素依然是公用的,也就是说,mutableCopyArray[0]也指向element,[mutableCopyArray[0] addObject:***]会影响到array的结果。

id deepMutableCopyArray = [array test_deepMutableCopy];

这一句代码对应的实现是深拷贝,首先它也拷贝了容器自身,返回了一个新的可变数组,指向不同的内存地址。

其次,对内部的元素也进行了拷贝动作,也就是说deepMutableCopyArray[0]是一个新的可变数组,和原来的element是两个数组,修改[deepMutableCopyArray[0] addObject:***]并不会影响到array的结果。

时间: 2024-10-11 04:25:56

iOS之深拷贝与浅拷贝的相关文章

iOS开发——深拷贝与浅拷贝详解

深拷贝和浅拷贝这个问题在面试中常常被问到,而在实际开发中,只要稍有不慎,就会在这里出现问题.尤其对于初学者来说,我们有必要来好好研究下这个概念.我会以实际代码来演示,相关示例代码上传至 这里 . 首先通过一句话来解释:深拷贝就是内容拷贝,浅拷贝就是指针拷贝. 深拷贝就是拷贝出和原来仅仅是值一样,但是内存地址完全不一样的新的对象,创建后和原对象没有任何关系.浅拷贝就是拷贝指向原来对象的指针,使原对象的引用计数+1,可以理解为创建了一个指向原对象的新指针而已,并没有创建一个全新的对象. (1)非容器

IOS学习—深拷贝和浅拷贝

// // main.m // 深拷贝与浅拷贝 // // Created by on 15/4/10. // Copyright (c) 2015年 apple. All rights reserved. // #import <Foundation/Foundation.h> #import "Student.h" #import "GoodStudent.h" int main(int argc, const char * argv[]) { @a

iOS中深拷贝和浅拷贝

参考文章:http://www.cnblogs.com/ydhliphonedev/archive/2012/04/27/2473927.html ios提供了copy和mutablecopy方法,顾名思义,copy就是复制了一个imutable的对象,而mutablecopy就是复制了一个mutable的对象.以下将举几个例子来说明. 1.系统的非容器类对象:这里指的是NSString.NSNumber等等一类的对象. NSString *string = @"origion"; N

IOS开发--深拷贝与浅拷贝(mutableCopy与Copy)详解

这里主要侧重于集合类的深浅拷贝,主要事因为工作的时候遇到这个问题.有不足的地方欢迎指正,转载请注明. 首先我们需要有这样的一个前提: [array addObject:obj];这样obj的引用计数会增加1,如果使用remove则obj的引用计数会减一.ios对集合的内存处理就是这样的.那么,假设obj只被array拥有:id temp = [array objectAtIndex:0];[array removeObjectAtIndex:0];如果你再要使用temp就会出错,因为这个时候ob

iOS中深拷贝、浅拷贝和retain的区别

浅拷贝:浅拷贝是对object对象的指针拷贝,让指针指向同一块内存地址,“对象永远只有一个",浅拷贝使对象的引用计数器+1.代码如下: 可以看出不可变字符串的指针指向了同一地址,并没有重新开辟内存. 深拷贝:深拷贝是对object对象的复制,保留原对象的值,开辟新的内存地址. 如图中代码,声明一个可变数组,为WXDObject类添加一个用copy修饰的属性,在类的实现后将指针指向可变数组,打印两者的地址发现地址发生了变化.所以用copy修饰可变对象,将会进行深拷贝. retain修饰:将上面ar

IOS中复制对象的用法及深拷贝和浅拷贝详解

亲爱的网友,我这里有套课程想和大家分享,如果对这个课程有兴趣的,可以加我的QQ2059055336和我联系. 课程内容简介 我们软件是基于移动设备的.所以我们必然的选择了安卓作为我们的开发工具.课程中,我们将简要的介绍Android的基本概念,然后进行我们的实战开发.在开发中,大家讲学习到基本的组件,适配UI,数据的存储,多线程下载,开机广播,闹钟提醒,短信发送等实际项目开发中碰到的有用的知识点.通过课程学习,让大家能够掌握Android软件开发的流程,注意点,及优化.帮助大家迅速的掌握Andr

iOS深拷贝与浅拷贝

概念 对象拷贝有两种方式:浅复制和深复制.顾名思义,浅复制,并不拷贝对象本身,仅仅是拷贝指向对象的指针:深复制是直接拷贝整个对象内存到另一块内存中. 如图详解: 再简单些说:浅复制就是指针拷贝:深复制就是内容拷贝. 集合的浅拷贝 (shallow copy) 集合的浅复制有非常多种方法.当你进行浅复制时,会向原始的集合发送retain消息,引用计数加1,同时指针被拷贝到新的集合. 浅拷贝的例子: NSArray *shallowCopyArray = [someArray copyWithZon

iOS中的 深拷贝和浅拷贝

#import <Foundation/Foundation.h> int main(int argc, const char * argv[]) { // 一: copy 与 retain 的区别 // 谁才有引用计数的概念: // 1. 堆区空间才有引用计数概念. // 2. 堆区的对象才会有引用计数. //%ld: - 1 %lu:18446744073709551615 //retain:始终是浅拷贝.引用计数每次加一. //返回对象是否可变与被复制的对象保持一致. //copy:对于

OC中self.xxx和_xxx访问的区别,深拷贝和浅拷贝的区别

初学iOS时候,发现有的代码通过self.xxx访问,有时通过_xxx访问,一直搞不清楚有什么区别.其实,通过self.xxx是对属性进行访问,本质是调用属性的setter方法,属性的引用计数器会+1:_xxx是直接对成员属性进行访问,是对指针的赋值,引用计数器没发生改变.下面,通过代码来看一下. 定义属性: @property (nonatomic, copy)NSString *strCopy1; @property (nonatomic, copy)NSString *strCopy2;