Objective-C 谈谈深浅拷贝,copy和mutable copy都不是完全拷贝

(一)字符串中的指针赋值,copy和mutablecopy

NSString和NSString

 (1)指针赋值

肯定指向同一个字符串地址。

(2)copy(和直接指向一样)

    NSString *[email protected]"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 *[email protected]"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 *[email protected]"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];
    [email protected]"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];
    [email protected]"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

所以一个比较好的方法就是像上个博客里面说的,先归档,再解开

    NSData *data = [NSKeyedArchiver archivedDataWithRootObject:stu1];
    Student *stu2 = [NSKeyedUnarchiver unarchiveObjectWithData:data];

啊完全拷贝啊~~一切都清净了。。。

时间: 2024-10-23 18:45:50

Objective-C 谈谈深浅拷贝,copy和mutable copy都不是完全拷贝的相关文章

复制对象 copy 与mutable copy

转载 :  http://blog.csdn.net/u010962810/article/details/18887841 通过copy方法可以创建可变对象或不可变对象的不可变副本,对于不可变副本,其对象的值不可以改变. 通过mutableCopy方法可以创建可变对象或不可变对象的可变副本,对于可变副本其对象是可变的. 复制分为浅复制和深复制两种:浅复制只是复制对象的引用,并没有复制对象的具体内容.深复制则创建了要复制对象的具体内容,并返回对象副本的引用. 对于复制Foundation中的对象

深浅copy,何为深浅copy,深copy和浅copy两者有何不同

copy,拷贝,顾名思义,自然是把东西复制过来,呈现在眼前的是一样的,例如: a = [1,2,3,4,5] b = a b.append(6) print(a,b) 输出: [1, 2, 3, 4, 5, 6] [1, 2, 3, 4, 5, 6] 很明显,a和b的值是一样的.因为对于赋值运算来讲,a与b指向的是同一内存地址,所以他们完全是一样的 浅copy: a = [1,2,3,4,[5]] b = copy.copy(a) b[4].append(6) print(a) print(b)

copy&amp;mutableCopy 浅拷贝(shallow copy)深拷贝 (deep copy)

本文来自 这里,原文作者微博MicroCai 概念 对象拷贝有两种方式:浅复制和深复制.顾名思义,浅复制,并不拷贝对象本身,仅仅是拷贝指向对象的指针:深复制是直接拷贝整个对象内存到另一块内存中. 一图以蔽之 再简单些说:浅复制就是指针拷贝:深复制就是内容拷贝. 集合的浅复制 (shallow copy) 集合的浅复制有非常多种方法.当你进行浅复制时,会向原始的集合发送retain消息,引用计数加1,同时指针被拷贝到新的集合. 现在让我们看一些浅复制的例子: NSArray *shallowCop

Shallow copy and Deep copy

一.来自wikipidia的解释: Shallow copy One method of copying an object is the shallow copy. In that case a new object B is created, and the fields values of A are copied over to B. This is also known as a field-by-field copy,field-for-field copy, or field co

(五)聊一聊深Copy与浅Copy

一.关于浅copy与深copy 首先说明一下: 在python中,赋值其实就是对象的引用,变量就是对象的一个标签,如果把内存对象比喻成一个个房间,那么变量就是门牌号. 深copy与浅copy只是针对可变类型而言,对于不可变类型,无论深浅,值相等,内存地址一样,一旦值发生变化,相当于再创建一个对象. 浅copy有3种方法: a=[1,2,3,["a","b"],22] a1=a[:]  切片操作 a2=list(a)  工厂函数 a3=copy.copy(a)  或

理解一下python中的浅copy和深copy

最近在学习过程中,了解了一下,浅copy和深copy,做个记录. 所谓浅拷贝就是对引用的拷贝,所谓深拷贝就是对对象的资源的拷贝. 首先,对赋值操作我们要有以下认识: 赋值是将一个对象的地址赋值给一个变量,让变量指向该地址( 旧瓶装旧酒 ). 修改不可变对象(str.tuple)需要开辟新的空间 修改可变对象(list等)不需要开辟新的空间 浅拷贝仅仅复制了容器中元素的地址 >>> user = ['tom', ['age', 20]] >>> user_new = us

C++类禁止copy构造函数和copy assign操作符

C++类禁止copy构造函数和copy assign操作符 在C++类中,编译器可以暗自为class创建default构造函数.copy构造函数.copy assignment操作符,以及析构函数.注意,这些编译器产生出来的函数都是public的,为了阻止这些函数被创建出来,我们可以把它们声明为private,这样就阻止了编译器暗自创建其对应版本函数. class Node { public: Node(int _data = 0) : data(_data) {} int get() cons

猫猫整理问题之:copy,对象自定义copy

猫猫分享,必须精品 原文地址:http://blog.csdn.net/u013357243?viewmode=contents copy copy的正目的 copy 目的:建立一个副本,彼此修改,各不干扰 Copy(不可变)和MutableCopy(可变)针对Foundation框架的数据类型. 对于自定义类,copy就是可变的. 可变数组的copy 这里用NSMutableArray为例子. // 可变=>可变&不可变,内存地址都会变化 void copyDemo1() { NSMuta

Summary: Deep Copy vs. Shallow Copy vs. Lazy Copy

Object copy An object copy is an action in computing where a data object has its attributes copied to another object of the same data type. An object is a composite data type in object-oriented programming languages. The copying of data is one of the