Object-C的浅拷贝与深拷贝区别

1、要了解浅拷贝与深拷贝,首要的是理解浅拷贝是什么深拷贝是什么

<1>浅拷贝:就相当于retain,只copy了一个对象的引用,和本身是同一个对象,就相当于影子。

<2>深拷贝:从新开辟了一块内存空间,用来存放原来对象里面的东西,这个时候,copy出来的对象和原来的对象不是同一个对象,他们的内容一样,就相当于克隆人。

<3>拷贝出来的的对象是什么类型取决于使用什么拷贝。

2、拷贝的用法

<1>不可变copy拷贝不可变对象(浅拷贝):

NSArray *array=[[NSArray alloc]initWithObjects:@"1",@"2", nil];
NSArray *array1=[array copy];
NSLog(@"array1=%@",array1);
NSLog(@"array=%p,array1=%p",array,array1);
NSLog(@"array = %lu ,array1 = %lu",[array retainCount],[array1 retainCount]);

其输出结果:

看输出结果反馈出:对不可变数组array进行不可变copy时,拷贝出来的array1是跟array一样的对象且两个数组的引用计数都+1,相当于对array本身的一个引用而已。

<2>不可变copy拷贝可变对象(深拷贝):

NSMutableArray *mArray=[[NSMutableArray alloc]initWithObjects:@"1",@"2", nil];
NSArray *array=[mArray copy];
NSLog(@"mArray=%p,array=%p",mArray,array);
NSLog(@"array=%@",array);
NSLog(@"array的类型%@",[array class]);
NSLog(@"mArray = %lu ,array = %lu",[mArray retainCount],[array retainCount]);

其输出结果:

看输出结果反馈出:对可变数组mArray进行不可变copy操作,拷贝出来的array数组与mArray数组的内存地址是不一样的且两块内存地址内容是相同的,而内容是一样的且引用计数不发生改变,array数组的类型不变依旧是不可变数组。由此可以得出不可变copy拷贝可变对象是深拷贝。

<3>可变copy拷贝不可变对象(深拷贝):

NSArray *array=[[NSArray alloc]initWithObjects:@"1",@"2", nil];
NSMutableArray *mArray=[array mutableCopy];
NSLog(@"-%@",[[array mutableCopy] class]);
NSLog(@"array=%p,mArray=%p",array,mArray);
NSLog(@"mArray=%@",mArray);
NSLog(@"mArray = %lu ,array = %lu",[mArray retainCount],[array retainCount]);

其输出结果:

看输出结果反馈出:对不可变数组array进行可变可变copy操作,拷贝出来的mArray数组与array数组的内存地址不同且两块内存地址内容是相同的,且拷贝出来的对象是可变的,引用计数并没有发生改变,由此可以得出可变copy拷贝不可变对象是深拷贝。

<4>可变copy拷贝可变对象(深拷贝):

 NSMutableArray *mArray=[[NSMutableArray alloc]initWithObjects:@"1",@"2", nil];
 NSMutableArray *array=[mArray mutableCopy];
 NSLog(@"%@",[[mArray mutableCopy] class]);
 NSLog(@"mArray=%p,array=%p",mArray,array);
 NSLog(@"array=%@",array);
 NSLog(@"mArray = %lu ,array = %lu",[mArray retainCount],[array retainCount]);

其输出结果:

看输出结果反馈出:对可变数组array进行可变可变copy操作,拷贝出来的array数组与mArray数组的内存地址不同且两块内存地址内容是相同的,且拷贝出来的对象是可变的,没有引起引用计数的变化,由此可以得出可变copy拷贝可变对象是深拷贝。

<5>自定义类的copy:

自定义一个person类

.h文件

#import <Foundation/Foundation.h>
//要实现copy必须遵守NSCopying或者NSMutableCopying协议,这里面有一个必须实现的协议copyWithZone:
@interface Person : NSObject<NSCopying>
@property(retain,nonatomic)NSString *name;

@property(copy,nonatomic)NSArray *array;
@property(copy,nonatomic)NSMutableArray *mArray;

@end

.m文件

#import "Person.h"

@implementation Person
-(id)copyWithZone:(NSZone *)zone
{
    Person *pp=[[Person alloc]init];
//    NSLog(@"pp=%p",pp);
    pp.name=self.name;
    return pp;
}
@end

在main.m文件中,导入person类头文件且添加下列代码

/*
     要实现copy必须遵守NSCopying或者NSMutableCopying协议,这里面有一个必须实现的协议copyWithZone:
*/

    Person *p=[[Person alloc]init];
    p.name=@"张三";
    Person *p1=[p copy];
    NSLog(@"p=%p,p1=%p",p,p1);
    NSLog(@"p1的名字为%@",p1.name);

运行结果得到:

可以得出:自定义对象进行copy操作得到的是两块补一样的内存地址,且内容是一样的。

<6>属性的copy:

1、copy修饰不可变属性的时候,就相当于retain

2、copy修饰可变属性的时候,相当于不可变copy拷贝可变对象。属于深拷贝,这个时候,属性和对属性赋值的对象的内存都需要单独管理

3、建议对象类型都是用retain

时间: 2024-10-11 15:56:29

Object-C的浅拷贝与深拷贝区别的相关文章

C# 中浅拷贝与深拷贝区别

转:https://www.cnblogs.com/xugang/archive/2010/09/09/1822555.html 也许会有人这样解释C# 中浅拷贝与深拷贝区别: 浅拷贝是对引用类型拷贝地址,对值类型直接进行拷贝. 不能说它完全错误,但至少还不够严谨.比如:string 类型咋说? 其实,我们可以通过实践来寻找答案. 首先,定义以下类型: int .string .enum .struct .class .int[ ] .string[ ] 代码如下:     //枚举     p

C# 浅拷贝与深拷贝区别

浅拷贝:给对象拷贝一份新的对象.浅拷贝的定义—— 只对值类型(或string)类型分配新的内存地址.深拷贝:给对象拷贝一份全新的对象.深拷贝的定义—— 对值类型分配新的内存地址,引用类型.以及引用类型的内 http://blog.csdn.net/lai123wei/article/details/7217365 C# 浅拷贝与深拷贝区别,布布扣,bubuko.com

JavaScript非构造函数的继承( object()方法、浅拷贝与深拷贝 )

一.什么是"非构造函数"的继承? 比如,现在有一个对象,叫做"中国人". var Chinese = { nation:'中国' }; 还有一个对象,叫做"程序员". var Programmer ={ career:'程序员' } 要怎样才能让"程序员"去继承"中国人"? 这里两个对象都是普通对象,而非构造函数,无法用构造函数方法实现"继承". 二.object()方法 functio

经典前端面试题: Object.assign 是浅拷贝还是深拷贝?实现深拷贝的方法有哪些?

Object.assign() 方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象.它将返回目标对象. 如果目标对象中的属性具有相同的键,则属性将被源对象中的属性覆盖.后面的源对象的属性将类似地覆盖前面的源对象的属性. Object.assign 方法只会拷贝源对象自身的并且可枚举的属性到目标对象.该方法使用源对象的[[Get]]和目标对象的[[Set]],所以它会调用相关 getter 和 setter.因此,它分配属性,而不仅仅是复制或定义新的属性.如果合并源包含getter,这可

C++浅拷贝和深拷贝的区别

c++默认的拷贝构造函数是浅拷贝 浅拷贝就是对象的数据成员之间的简单赋值,如你设计了一个没有类而没有提供它的复制构造函数,当用该类的一个对象去给令一个对象赋值时所执行的过程就是浅拷贝,如:class A { public: A(int _data) : data(_data){} A(){}private: int data; };int main() { A a(5), b = a; // 仅仅是数据成员之间的赋值 }这一句b = a;就是浅拷贝,执行完这句后b.data = 5;如果对象中没

关于python中赋值、浅拷贝、深拷贝之间区别的深入分析

大家都知道,在python中复制一个对象有多种方法,其中常用的是赋值.浅拷贝和深拷贝,这三者之间有哪些区别和哪些坑呢? 首先,定义一下: 赋值:  a =1    b =a    a赋值给了b 浅拷贝: a = []  b = a.copy() 或者import copy             b = copy.copy(a) 深拷贝:import copy  a = []   b = copy.deepcopy(a) 未完待续

Python中浅拷贝和深拷贝的区别

Python中浅拷贝和深拷贝的区别 浅拷贝和深拷贝示意图 如上图,简单点说 1. copy.copy 浅拷贝 只拷贝父对象,不会拷贝对象的内部的子对象. 2. copy.deepcopy 深拷贝 拷贝对象及其子对象 数字,字符串是不可变类型 列表,字典是可变类型 我们看下面的案例 案例一:浅拷贝 >>> import copy     #导入copy模块                >>> s=['name',['savings',100.0]] #赋值给s >

浅拷贝与深拷贝的实现方式、区别;deepcopy如果你来设计,如何实现(一)

浅拷贝与深拷贝的实现方式.区别:deepcopy如果你来设计,如何实现: copy浅拷贝:没有拷贝子对象,所以原始数据改变,子对象改变 deepcopy深拷贝:包含对象里面的子对象的拷贝,所以原始对象的改变不会造成深拷贝里的任何子元素的改变 Python里的赋值符号"="只是将对象进行了引用,如果想新开辟进行了引用,如果想新开辟地址new出一个新对象,要用copy模块里copy.copy(),但是用这个方法得到的对象就是新对象,但是数据还是引用. 如果要完全得到一个一模一样的对象,要用

python中赋值,浅拷贝,深拷贝的区别

1.首先,对被操作对象分类,对于不可变对象而言,如字符串.数字.tuple等,这三种操作是等价的,都是引用 import copy a='apple'b=ac=copy.copy(a)d=copy.deepcopy(a)print(id(a))print(id(b))print(id(c))print(id(d) 输出: 1840734496184073449618407344961840734496 可见,这四个变量都指向同一块内存地址,即'apple'这个字符串所在的地址 2.对可变对象(或