zoukankan      html  css  js  c++  java
  • OC-深浅复制

    【OC学习-26】对象的浅拷贝和深拷贝——关键在于属性是否可被拷贝

    拷贝用到协议,如果这个类创建对象后,这个对象要被拷贝,那么这个类就需要用到拷贝协议,分两种:<NSCopying>和<NSMutableCopying>相当于一个是拷贝,另一个是拷贝后可修改。

    (1)浅拷贝的案例。有一个Person类,它创建一个person1对象后,用person1再拷贝一个person2出来。

    //Person类的Person.h文件
    #import <Foundation/Foundation.h>
    //因为这个类要支持拷贝,所以需要引入拷贝协议,有两种,后一种拷贝后可修改
    @interface Person : NSObject<NSCopying,NSMutableCopying>
    @property(nonatomic,copy) NSString* name;
    @property(nonatomic,retain) NSNumber* age;
    @end
    //这是Person.m文件
    #import "Person.h"
    @implementation Person
    //这是系统函数,可以直接拷贝过来
    - (id)copyWithZone:(NSZone *)zone{
      Person *person=[[[self class]allocWithZone:zone]init]; //默认格式
      person.name=_name; //浅拷贝就是直接赋值即可
      person.age=_age;  //浅拷贝就是直接赋值即可
      return person;
    }
    @end
    //main.m文件
    #import <Foundation/Foundation.h>
    #import "Person.h"//记得引入头文件
    int main(int argc, const char * argv[])
    {
      @autoreleasepool {
        Person *person1=[[Person alloc]init];
        person1.name=@"jack";
        person1.age=@18;
        Person *person2=[person1 copy];
        NSLog(@"%p,%p",person1,person2);//输入两个对象地址,不同
        NSLog(@"%p,%p",person1.age,person2.age);//输出两个对象的属性地址,相同
      }
      return 0;
    }

    结果:

    0x1002036f0,0x100200330 //不同
    0x1227,0x1227 //相同

    (2)深拷贝的案例。

    按道理是只需要把Person.m里面的赋值语句改成下面的样子,就能实现深拷贝:

    person.name=[_name copy]; 
    person.age=[_age copy];

    但是,因为cocoa优化过了,所以有如下规则:

    a:如果是Foundation框架里的不可变对象,就是Array,NSString等创建的对象,直接用copy来拷贝相当于retain,也就是属性还是同一个;

    b:如果是用mutableCopy来拷贝,不管是可变还是不可变对象,属性神马的都直接拷贝了一份,即真正意义上得拷贝,它拷贝出来的对象统统都是可变的;

    c:如果是可变对象,我们用copy也能实现真正意义上的拷贝,但是拷贝出来的对象是不可变的。

    所以,我们拿name实验(因为age没有mutableCopy)实现语句的修改:

    person.name=[_name mutableCopy]
    person.age=[_age copy];

    然后再输出person1和person2的name属性的地址,发现就不同了。

    总结:

    浅拷贝和深拷贝在实际项目中不常用,可以做一般了解。

     

     

     

    OC-深浅复制

     

       浅 复 制:在复制操作时,对于被复制的对象的每一层复制都是指针复制

       深 复 制:在复制操作时,对于被复制的对象至少有一层复制是对象复制

       完全复制:在复制操作时,对于被复制的对象的每一层复制都是对象复制。

     

            注:1在复制操作时,对于对象有n层是对象复制,我们可称作n级深复制,此处n应大于等于1。

                  2对于完全复制如何实现(目前通用的办法是:迭代法和归档),这里后续是否添加视情况而定,

                  暂时不做讲解。

              3、指针复制俗称指针拷贝,对象复制也俗称内容拷贝。

     

    retain始终是浅复制。引用计数每次加一。返回对象是否可变与被复制的对象保持一致。

     

    copy:对于可变对象为深复制,引用计数不改变;对于不可变对象是浅复制,

             引用计数每次加一。始终返回一个不可变对象。

     

    mutableCopy:始终是深复制,引用计数不改变。始终返回一个可变对象。

     

    不可变对象:值发生改变,其内存首地址随之改变。

       可变对象:无论值是否改变,其内存首地址都不随之改变。

       引用计数:为了让使用者清楚的知道,该对象有多少个拥有者(即有多少个指针指向同一内存地址)。

     

    亲爱的读者朋友,下面是我用于验证的详细代码。对于验证还能得出什么结论,我希望朋友们能自己多多发掘一下。这里只做以上几点总结。对于本文有任何疑问请与我联系,欢迎指出本文不足的地方,谢谢!

    #import<Foundation/Foundation.h>

     

    int main (int argc, const char * argv[])

    {

     

        @autoreleasepool {

     

        //第一种:非容器类不可变对象

     

            NSString *str1=@"one day";

            

              printf("n初始化赋值引用计数为::::%lu",str1.retainCount);

            NSString *strCopy1=[str1 retain];

              printf("n继续retain引用计数为:::%lu",str1.retainCount);

            NSString *strCopy2=[str1 copy];

              printf("n继续copy后引用计数为::::%lu",str1.retainCount);

            NSString *strCopy3=[str1 mutableCopy];

                    printf("n继续mutableCopy后为:::%lun",str1.retainCount);

            

            printf("n非容器类不可变对象n原始地址::::::::::%p",str1);

            printf("nretain复制::::::::%p",strCopy1);

            printf("ncopy复制::::::::::%p",strCopy2);

            printf("nmutableCopy复制:::%p",strCopy3);

     

        //这里说明该类型不存在引用计数的概念

     

      // 初始化赋值引用计数为:18446744073709551615

      // 继续retain引用计数为:18446744073709551615

      // 继续copy后引用计数为:18446744073709551615

      // 继续mutableCopy后为:18446744073709551615

       

       //非容器类不可变对象

       //原始地址::::::::::0x1000033d0

       //retain复制::::::::0x1000033d0//浅复制

       //copy复制::::::::::0x1000033d0//浅复制

       //mutableCopy复制:::0x10010c420//深复制

      

     

          printf("n");

     //第二种:容器类不可变数组

     

            NSArray *array1= [NSArray arrayWithObjects:@"a",@"b",@"c",@"d",nil];

            

              printf("n初始化赋值引用计数为::::::::::::%lu",array1.retainCount);

            NSArray *arrayCopy1 = [array1 retain];

              printf("n继续retain后引用计数为:::::::::%lu",array1.retainCount);

            NSArray *arrayCopy2 = [array1 copy];

              printf("n继续copy后引用计数为:::::::::::%lu",array1.retainCount);

            NSArray *arrayCopy3 = [array1 mutableCopy];

              printf("n继续mutableCopy后引用计数为::::%lun",array1.retainCount);

            

        printf("n容器类不可变数组n原始地址::::::::::%ptt%p",array1,[array1 objectAtIndex:1]);

            printf("nretain复制::::::::%pt%p",arrayCopy1,[arrayCopy1 objectAtIndex:1]);

            printf("ncopy复制::::::::::%pt%p",arrayCopy2,[arrayCopy2 objectAtIndex:1]);

            printf("nmutableCopy复制:::%pt%p",arrayCopy3,[arrayCopy3 objectAtIndex:1]);

            

       

        //初始化赋值引用计数为::::::::::::1

        //继续retain后引用计数为:::::::::2

        //继续copy后引用计数为:::::::::::3

        //继续mutableCopy后引用计数为::::3

     

        //容器类不可变数组

        //原始地址::::::::::0x10010c6b0 0x100003410

        //retain复制::::::::0x10010c6b0 0x100003410//浅复制

        //copy复制::::::::::0x10010c6b0 0x100003410//浅复制

        //mutableCopy复制:::0x10010c760 0x100003410//深复制

     

        

            printf("n");

     //第三种:非容器类可变对象

     

            NSMutableString *str2=[NSMutableString stringWithString:@"two day"];

            

              printf("n初始化赋值引用计数为::::::::::::%lu",str2.retainCount);

            NSMutableString *strCpy1=[str2 retain];

              printf("n继续retain后引用计数为:::::::::%lu",str2.retainCount);

            NSMutableString *strCpy2=[str2 copy];

              printf("n继续copy后引用计数为:::::::::::%lu",str2.retainCount);

            NSMutableString *strCpy3=[str2 mutableCopy];

                    printf("n继续mutableCopy后引用计数为::::%lun",str2.retainCount);

            

            printf("n非容器类可变对象n原始地址::::::::::%p",str2);

            printf("nretin复制::::::::%p",strCpy1);

            printf("ncopy复制::::::::::%p",strCpy2);

            printf("nmutableCopy复制:::%p",strCpy3);

           

     

     

             //初始化赋值引用计数为::::::::::::1

             //继续retain后引用计数为:::::::::2

             //继续copy后引用计数为:::::::::::2

             //继续mutableCopy后引用计数为::::2

     

             //非容器类可变对象

             //原始地址::::::::::0x10010c560

             //retain复制::::::::0x10010c560//浅复制

             //copy复制::::::::::0x100102720//深复制

           //mutableCopy复制:::0x10010c880//深复制

             

            printf("n");

     //第四种:容器类可变数组

     

      NSMutableArray *array2   = [NSMutableArrayarrayWithObjects:@"aa",@"bb",@"cc",@"dd",nil];

            

             printf("n初始化赋值引用计数为::::::::::%lu",array2.retainCount);

           NSMutableArray *arrayCpy1 = [array2 retain];

             printf("n继续retain后引用计数为:::::::%lu",array2.retainCount);

           NSMutableArray *arrayCpy2=[array2 copy];

             printf("n继续copy后引用计数为:::::::::%lu",array2.retainCount);

           NSMutableArray *arrayCpy3 = [array2 mutableCopy];

             printf("n继续mutableCopy后引用计数为::%lun",array2.retainCount);

            

           printf("n容器类可变数组n原始地址:::::::::::%pt%p",array2,[array2 objectAtIndex:1]);

           printf("nretain复制:::::::::%pt%p",arrayCpy1,[arrayCpy1 objectAtIndex:1]);

           printf("ncopy复制:::::::::::%pt%p",arrayCpy2,[arrayCpy2 objectAtIndex:1]);

           printf("nnmutableCopy复制:::%pt%p",arrayCpy3,[arrayCpy3 objectAtIndex:1]);

           

            

             //初始化赋值引用计数为::::::::::1

             //继续retain后引用计数为:::::::2

             //继续copy后引用计数为:::::::::2

             //继续mutableCopy后引用计数为::2

     

             //容器类可变数组

             //原始地址:::::::::::0x10010e6c0 0x1000034b0

             //retain复制:::::::::0x10010e6c0 0x1000034b0//浅复制

             //copy复制:::::::::::0x10010e790 0x1000034b0//深复制

             //nmutableCopy复制:::0x10010e7c0 0x1000034b0//深复制

             

            

     

        }

        return 0;

    }

     

  • 相关阅读:
    Hibernate 学习-3
    Hibernate反向工程使用心得
    MyEclipse中自动整合Spring3+Hibernate/JPA
    jsp页面不显示问题
    jstl获取当前系统时间的方法
    js实现12小时时钟
    从servlet跳到jsp页面,并用jstl 进行判断和显示方法
    jsp调用js文件时出现乱码
    常见异常总结
    js实现表单验证
  • 原文地址:https://www.cnblogs.com/iOS-mt/p/4121583.html
Copyright © 2011-2022 走看看