[解析]Objective-C 深浅拷贝

来源:互联网 发布:亚马逊和淘宝哪个大 编辑:程序博客网 时间:2024/04/25 16:43

在C++中,深浅拷贝的区别如下:

  • 浅拷贝。

缺省拷贝构造函数在拷贝过程中是按字节复制的,对于指针型成员变量只复制指针本身,而不复制指针所指向的目标,也就是两个对象中成员指针变量指向同一块内存

  • 深拷贝。对一个对象进行深拷贝,系统会为新对象变量中得每一个对象成员分配空间,并将原对象成员内容赋值给新对象对应的成员变量。

在iOS中,由于Objective-C自身提供了copy函数,但是深浅难辨,因此做下总结:

  • 非容器变量(immutable对象与mutable对象的区分)
    如下代码所示,可以得出结论,对于一个immutable对象,进行copy得到的对象是浅拷贝,进行mutableCopy得到的对象是深拷贝
    NSString *string = @"animal";    NSString *stringCopy11 = [string copy];    NSMutableString *stringMutableCopy11 = [string mutableCopy];    NSString *stringCopy12 = [string mutableCopy];//非法,容易错误操作    NSMutableString *stringMutableCopy12 = [string copy];//非法,容易错误操作    NSLog(@"%p \n%p \n%p \n%p \n%p", string, stringCopy11, stringCopy12, stringMutableCopy11, stringMutableCopy12);    //output    /*    2015-09-30 21:38:50.665 HelloWorld[966:49309]     0x10a0560a8     0x10a0560a8     0x7fd2f049eb00     0x7fd2f049ce90     0x10a0560a8    */

如下代码所示,可以得出结论,对于一个mutable对象,不管进行copy或mutableCopy得到的对象都是深拷贝

    NSMutableString *mutableString1 = [[NSMutableString alloc] initWithString:@"animal"];    NSString *stringCopy21 = [mutableString1 copy];    NSMutableString *stringMutableCopy21 = [mutableString1 mutableCopy];    NSMutableString *stringCopy22 = [mutableString1 copy];//非法,容易错误操作    NSString *stringMutableCopy22 = [mutableString1 mutableCopy];//非法,容易错误操作    NSLog(@"%p \n%p \n%p \n%p \n%p", mutableString1, stringCopy21, stringCopy22, stringMutableCopy21, stringMutableCopy22);    //output    /*    2015-09-30 21:38:50.665 HelloWorld[966:49309]     0x7fd2f049d8c0     0x7fd2f049d920     0x7fd2f049e430     0x7fd2f049d940     0x7fd2f049e450    */
  • 容器变量
    • 由以下实验可以看出,容器变量与非容器变量在进行copy与mutableCopy时的情况是一致的,关键在于容器变量如array中得对象都是浅拷贝,其都指向对应的同一块内存
    • trueDeepCopy31、trueDeepCopy33并不是真正意义上的深拷贝,其效果还是同前面讨论的一样并不是真正意义上得深拷贝,而trueDeepCopy32才算的上时真正意义上的深拷贝,因为其对象地址、对象成员地址都都与原来的对象不同。
    NSArray *a1 = @[@"dog", @"cat"];    NSArray *a2 = @[@"tiger", @"lion"];    NSArray *a3 = @[@"cow", @"sheep"];    NSArray *array = @[a1, a2, a3];    NSArray *arrayCopy11 = [array copy];    NSArray *arrayCopy12 = [array mutableCopy];    NSMutableArray *arrayMutableCopy11 = [array mutableCopy];    NSMutableArray *arrayMutableCopy12 = [array copy];    NSLog(@"%p %p %p \n%p %p %p\n%p %p %p\n%p %p %p\n%p %p %p", array, array[0], array[0][0],          arrayCopy11, arrayCopy11[0], arrayCopy11[0][0],          arrayCopy12, arrayCopy12[0], arrayCopy12[0][0],          arrayMutableCopy11, arrayMutableCopy11[0], arrayMutableCopy11[0][0],          arrayMutableCopy12, arrayMutableCopy12[0], arrayMutableCopy12[0][0]);//output    /*    2015-09-30 22:09:07.284 HelloWorld[1284:60191]     0x7fa2ab52fd80 0x7fa2ab52ffb0 0x10b0bc0b8     0x7fa2ab52fd80 0x7fa2ab52ffb0 0x10b0bc0b8    0x7fa2ab52fc20 0x7fa2ab52ffb0 0x10b0bc0b8    0x7fa2ab52f010 0x7fa2ab52ffb0 0x10b0bc0b8    0x7fa2ab52fd80 0x7fa2ab52ffb0 0x10b0bc0b8    */    NSMutableArray *mutableArray = [[NSMutableArray alloc] initWithArray:array];    NSArray *arrayCopy21 = [array copy];    NSArray *arrayCopy22 = [array mutableCopy];    NSMutableArray *arrayMutableCopy21 = [array mutableCopy];    NSMutableArray *arrayMutableCopy22 = [array copy];    NSLog(@"%p %p %p \n%p %p %p\n%p %p %p\n%p %p %p\n%p %p %p",          mutableArray, mutableArray[0], mutableArray[0][0],          arrayCopy21, arrayCopy21[0], arrayCopy21[0][0],          arrayCopy22, arrayCopy22[0], arrayCopy22[0][0],          arrayMutableCopy21, arrayMutableCopy21[0], arrayMutableCopy21[0][0],          arrayMutableCopy22, arrayMutableCopy22[0], arrayMutableCopy22[0][0]);    //output    /*    2015-09-30 22:09:07.284 HelloWorld[1284:60191]     0x7fa2ab52f060 0x7fa2ab52ffb0 0x10b0bc0b8     0x7fa2ab52fd80 0x7fa2ab52ffb0 0x10b0bc0b8    0x7fa2ab52f0b0 0x7fa2ab52ffb0 0x10b0bc0b8    0x7fa2ab52f100 0x7fa2ab52ffb0 0x10b0bc0b8    0x7fa2ab52fd80 0x7fa2ab52ffb0 0x10b0bc0b8    */    NSArray *trueDeepCopy31 = [[NSArray alloc] initWithArray:array copyItems:YES];    NSArray *trueDeepCopy32 = [NSKeyedUnarchiver unarchiveObjectWithData:[NSKeyedArchiver archivedDataWithRootObject:array]];    NSMutableArray *trueDeepCopy33 = [[NSMutableArray alloc] initWithArray:array copyItems:YES];    NSLog(@"%p %p %p \n%p %p %p\n%p %p %p", trueDeepCopy31, trueDeepCopy31[0], trueDeepCopy31[0][0],          trueDeepCopy32, trueDeepCopy32[0], trueDeepCopy32[0][0],          trueDeepCopy33, trueDeepCopy33[0], trueDeepCopy33[0][0]);    //output    /*    2015-09-30 23:13:18.877 HelloWorld[637:12672]     0x7fe7414a8d90 0x7fe7414a9f00 0x10a5050b8     0x7fe7414a96a0 0x7fe7414a9f00 0x10a5050b8    0x7fe7414a9770 0x7fe7414a9f00 0x10a5050b8    0x7fe7414aa070 0x7fe7414a9f00 0x10a5050b8    0x7fe7414a96a0 0x7fe7414a9f00 0x10a5050b8    2015-09-30 23:13:18.877 HelloWorld[637:12672]     0x7fe7414aa0c0 0x7fe7414a9f00 0x10a5050b8     0x7fe7414aaed0 0x7fe7414aab80 0x7fe7414aab20    0x7fe7414aaae0 0x7fe7414a9f00 0x10a5050b8    */
  • 自定义拷贝
    自定义拷贝需要继承NSCopying、NSMutableCopying协议,重写以下两个方法。
- (id)copyWithZone:(NSZone *)zone;- (id)mutableCopyWithZone:(NSZone *)zone;
//示例//FSJAnimal.h@interface FSJAnimal : NSObject@property(nonatomic, copy) NSString *name;@property(nonatomic, strong) NSSet *families;-(id)initWithName:(NSString *)name;@end//FSJAnimal.m@interface FSJAnimal()<NSCopying, NSMutableCopying> @end@implementation FSJAnimal@synthesize name;@synthesize families;//懒初始化-(NSSet*)families{    return [_internalFamilies copy];} -(id)initWithName:(NSString *)name{    if(self = [super init])    {        _name = name;        _internalFamilies = [[NSMutableSet alloc] init];    }    return self;}- (id)copyWithZone:(NSZone *)zone{    FSJAnimal *copy = [[[self class] alloc] init];    copy->name = [name copy];    copy->families = [families copy];    return copy;}- (id)mutableCopyWithZone:(NSZone *)zone{    FSJAnimal *copy = [[[self class] alloc] init];    copy->name = [name mutableCopy];    copy->families = [families mutableCopy];    return copy;}@end
0 0
原创粉丝点击