zoukankan      html  css  js  c++  java
  • 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;
  • 相关阅读:
    mysql,apache,php的关系
    简析 Tomcat 、Nginx 与 Apache 的区别
    Linux中涉及到环境变量的文件
    如何在Linux启动的时候执行一个命令
    sed的额外用法(网摘)
    shell脚本执行方式
    在rhel7上搭建centos7的yum源
    MYSQL三种安装方式--二进制包安装
    ssh连接不上排查方法总结
    MySQL启动很慢的原因
  • 原文地址:https://www.cnblogs.com/yangwenhuan/p/9572774.html
Copyright © 2011-2022 走看看