• Objective-C 浅拷贝与深拷贝


    一个Objective-C对象通常分配在堆上,并有一个或者多个指针指向它。如下代码及其关系图所示:

    NSObject *obj1 = [[NSObject alloc] init];
    NSObject *obj2 = obj1; 

    所谓浅拷贝与深拷贝,需要分为非容器类(如NSString)与容器类(如NSArray)来理解。如下表格所示:

    与拷贝相关的两个系统函数是copy和mutableCopy,它们分别实现的是浅拷贝还是深拷贝呢?下面通过代码来验证:

    不可变非容器:
    NSString *str1 = @"this is a string.";
    NSString *str2 = [str1 copy]; // 浅拷贝
    NSString *str3 = [str1 mutableCopy]; // 深拷贝
    NSLog(@"str1 address[%p] content[%@]", str1, str1);
    NSLog(@"str2 address[%p] content[%@]", str2, str2);
    NSLog(@"str3 address[%p] content[%@]", str3, str3);
    
    输入:
    str1 address[0x102fc8058] content[this is a string.]
    str2 address[0x102fc8058] content[this is a string.]
    str3 address[0x6040002500e0] content[this is a string.]
    可变非容器:
    NSMutableString *str4 = [[NSMutableString alloc] initWithString:@"this is a string."];
    NSMutableString *str5 = [str4 copy]; // 深拷贝
    NSMutableString *str6 = [str4 mutableCopy]; // 深拷贝
    NSLog(@"str4 address[%p] content[%@]", str4, str4);
    NSLog(@"str5 address[%p] content[%@]", str5, str5);
    NSLog(@"str6 address[%p] content[%@]", str6, str6);
    
    输出:
    str4 address[0x60800024efd0] content[this is a string.]
    str5 address[0x608000257dc0] content[this is a string.]
    str6 address[0x608000257d90] content[this is a string.]
    不可变容器:
    NSArray *arr1 = @[[NSView new], [NSView new], [NSView new]];
    NSArray *arr2 = [arr1 copy]; // 浅拷贝
    NSArray *arr3 = [arr1 mutableCopy]; // 浅拷贝
    NSLog(@"arr1 address[%p] content[%@]", arr1, arr1);
    NSLog(@"arr2 address[%p] content[%@]", arr2, arr2);
    NSLog(@"arr3 address[%p] content[%@]", arr3, arr3);
    
    输出:
    arr1 address[0x60800004f9c0] content[(
        "<NSView: 0x6080001212c0>",
        "<NSView: 0x608000121040>",
        "<NSView: 0x6080001210e0>"
    )]
    arr2 address[0x60800004f9c0] content[(
        "<NSView: 0x6080001212c0>",
        "<NSView: 0x608000121040>",
        "<NSView: 0x6080001210e0>"
    )]
    arr3 address[0x60800004c120] content[(
        "<NSView: 0x6080001212c0>",
        "<NSView: 0x608000121040>",
        "<NSView: 0x6080001210e0>"
    )]
    可变容器:
    NSMutableArray *arr4 = [[NSMutableArray alloc] initWithArray:@[[NSView new], [NSView new], [NSView new]] ];
    NSMutableArray *arr5 = [arr4 copy]; // 浅拷贝
    NSMutableArray *arr6 = [arr4 mutableCopy]; // 浅拷贝
    NSLog(@"arr4 address[%p] content[%@]", arr4, arr4);
    NSLog(@"arr5 address[%p] content[%@]", arr5, arr5);
    NSLog(@"arr6 address[%p] content[%@]", arr6, arr6);
    
    输出:
    arr4 address[0x6000000599e0] content[(
        "<NSView: 0x600000121a40>",
        "<NSView: 0x600000121ae0>",
        "<NSView: 0x600000121b80>"
    )]
    arr5 address[0x6000000599b0] content[(
        "<NSView: 0x600000121a40>",
        "<NSView: 0x600000121ae0>",
        "<NSView: 0x600000121b80>"
    )]
    arr6 address[0x600000059980] content[(
        "<NSView: 0x600000121a40>",
        "<NSView: 0x600000121ae0>",
        "<NSView: 0x600000121b80>"
    )]

    可以看到,无论是copy,还是mutableCopy,都不会拷贝容器中的对象。另外,懂C++的同学可能注意到,Objective-C的数组地址并不是数组首个元素的地址。  

    注意:可以不拘泥于浅拷贝和深拷贝的概念,理解其中的原理即可。 

    自定义的类,如果要使用copy方法,就要实现NSCopying协议中的方法:

    - (id)copyWithZone:(NSZone*)zone; // zone参数没有用上,这是以前用来划分不同内存区的

    类似,如果要使用mutableCopy方法,则要实现NSMutableCopying协议中的方法:

    - (id)mutableCopyWithZone:(NSZone*)zone;
  • 相关阅读:
    CentOS7.5右键创建空白文档
    CentOS7.5安装配置conky(极简)
    CentOS7.5安装nodejs
    CentOS7.5安装网易云音乐
    CentOS7.5删除旧的内核
    CentOS7.5安装notepadqq
    CentOS7英文环境下使用中文输入法
    CentOS7安装Pycharm后无法使用日常的快捷键
    tomcat的work目录作用
    ORACLE获取某个时间段之间的月份列表
  • 原文地址:https://www.cnblogs.com/yangwenhuan/p/9572774.html
Copyright © 2020-2023  润新知