zoukankan      html  css  js  c++  java
  • 关于深复制与浅复制

    转自“红黑联盟”,网址:http://www.2cto.com/kf/201405/302273.html

    第一、复制对象的基本概念

    复制一个对象为副本,开辟一块新的内存来存储副本对象。

    第二、如果一个对象想具备复制的功能,必须实现协议和协议

    NSObject自带的常用的对象有:NSNumber、NSString、NSArray、NSDictionary、NSMutableArray、NSMutableDictionay、NSMutableString,copy产生的对象时不可变的,mutableCopy产生的对象时可变的

    第三、retain和copy的区别

        @autoreleasepool {
            NSMutableArray *array=[NSMutableArray arrayWithObjects:@"one",@"two",@"three",@"four",nil];
            NSMutableArray *retainArray=[array retain];
            [retainArray removeLastObject];
            for(NSString *str in array)
            {
                NSLog(@"the part is %@",str);
            }
            NSLog(@"the retaincount is %ld",[retainArray retainCount]);
            // insert code here...
            NSLog(@"Hello, World!");
            
        }
    
    

    结果:

    2014-05-19 10:58:22.639 objective[1095:303] the part is one
    2014-05-19 10:58:22.641 objective[1095:303] the part is two
    2014-05-19 10:58:22.641 objective[1095:303] the part is three
    2014-05-19 10:58:22.641 objective[1095:303] the retaincount is 2
    
    NSMutableArray *array=[NSMutableArray arrayWithObjects:@"one",@"two",@"three",@"four",nil];
            NSMutableArray *retainArray=[array mutableCopy];
            [retainArray removeLastObject];
            for(NSString *str in array)
            {
                NSLog(@"the part is %@",str);
            }
            NSLog(@"the retaincount is %ld",[retainArray retainCount]);
    



    结果

    2014-05-19 10:59:03.826 objective[1104:303] the part is one

    2014-05-19 10:59:03.828 objective[1104:303] the part is two

    2014-05-19 10:59:03.828 objective[1104:303] the part is three

    2014-05-19 10:59:03.829 objective[1104:303] the part is four

    2014-05-19 10:59:03.829 objective[1104:303] the retaincount is 1

    第四、COPY和MutableCopy的区别

    COPY 返回一个不可变对象的副本,MutalbeCopy返回一个可变对象的副本。

            NSArray *array=[NSArray arrayWithObjects:@"one",@"two", nil];
            NSMutableArray *array1=[array copy];
            [array1 addObject:@"three"];  //error
            NSMutableArray *array2=[array mutableCopy];
            [array2 addObject:@"three"];  //right
            // insert code here...
            NSLog(@"Hello, World!");
    


    第五、浅copy和深copy

    浅复制尽复制对象本身,对象里的属性、包含的对象不做复制

    深复制复制全部,包括对象的属性和其他对象

    Foundation框架支持复制的类,默认是浅复制

            NSMutableArray *array=[[NSMutableArray alloc] init];
            for(int i=0;i<3;i++)
            {
                NSObject *obj=[[NSObject alloc] init];
                [array addObject:obj];
                [obj release];
            }
            for(NSObject *obj1 in array)
            {
                NSLog(@"地址为 %p,引用计数是 %ld",obj1,obj1.retainCount);
            }
            NSMutableArray *array2=[array copy];
            for(NSObject *obj2 in array2)
            {
                NSLog(@"地址为 %p,引用计数是 %ld",obj2,obj2.retainCount);
            }
    
    2013-09-30 17:28:01.492 FDAS[681:303] 地址为 0x1001081f0,引用计数是 1
    2013-09-30 17:28:01.506 FDAS[681:303] 地址为 0x100108230,引用计数是 1
    2013-09-30 17:28:01.506 FDAS[681:303] 地址为 0x100108240,引用计数是 1
    2013-09-30 17:28:01.507 FDAS[681:303] 地址为 0x1001081f0,引用计数是 2
    2013-09-30 17:28:01.507 FDAS[681:303] 地址为 0x100108230,引用计数是 2
    2013-09-30 17:28:01.507 FDAS[681:303] 地址为 0x100108240,引用计数是 2
    

    第五、对象的自定义拷贝

    对象拥有复制特性,必须实现NSCopying,NSMutableCopying协议,实现该协议的copyWithZone方法和mutableCopyWithZone方法

    深拷贝和浅拷贝的区别就在于copyWithZone方法的实现,

    浅拷贝代码如下:

    #import 
    
    @interface Person : NSObject
    @property(nonatomic,retain)NSString *name;
    @property(nonatomic,retain)NSString *age;
    
    @end
    
    #import "Person.h"
    
    @implementation Person
    
    - (id)copyWithZone:(NSZone *)zone
    {
       //实现自定义浅拷贝
        Person *person=[[self class] allocWithZone:zone];
        person.age=_age;
        person.name=_name;
        return person;
    }
    @end
    


    main函数为:

        @autoreleasepool {
            
            Person *person=[[Person alloc] init];
            person.name=@"andy";
            person.age=@"20";
            
            Person *person2=[person copy];
            NSLog(@"person 地址为%p,person2地址为%p",person.name,person2.name);
        }
    
    

    输出结果为:

    2013-09-30 17:48:41.007 FDAS[732:303] person 地址为0x1000022c8,person2地址为0x1000022c8


    深拷贝代码如下:

    - (id)copyWithZone:(NSZone *)zone
    {
       //实现自定义浅拷贝
        Person *person=[[self class] allocWithZone:zone];
        person.age=[_age copy];
        person.name=[_age copy];
        return person;
    }
    

    结果:

    2013-09-30 17:55:13.603 FDAS[742:303] person 地址为0x1000022c8,person2地址为0x1000022e8
    
            NSArray *arr=[NSArray arrayWithObjects:@"one",@"two",nil];
            NSArray *arr2=[arr copy];
            NSLog(@"the dress of arr is %p the dress of arr2 is %p",arr,arr2);
            NSLog(@"the retainCount is %ld",arr.retainCount);
    
    


    执行结果为:

    2013-09-30 18:01:01.394 FDAS[787:303] the dress of arr is 0x100108320 the dress of arr2 is 0x100108320

    2013-09-30 18:01:01.396 FDAS[787:303] the retainCount is 2

    结果是一样的,是因为Foundation对于不可变复制对象而言,copy方法做了优化,相当于retain,故retaincount变成2.

    相当于 在copyWithZone方法中:return [self retain];

    第六、copy、mutableCopy和retain之间的关系

    在Foundation对象中,copy是一个不可变的对象时,作用相当于retain

    当使用mutableCopy时,不管源对象是否可变,副本是可变的,并且实现真正意义上的copy

    当我们使用copy一个可变对象时,副本对象是不可变的。


    关于深拷贝和浅拷贝:

    第一、浅拷贝:

        Car *car=[[[self class] allocWithZone:zone] init];
        car.engine=_engine;
        car.name=_name;
        car.weight=_weight;
        return car;
    

    测试代码:

     Car *car = [[Car alloc] init];
            Engine *engine = [[Engine alloc] init];
            car.engine = engine;
            [engine release];
            //NSLog(@"engine retaincount is %lu",[engine retainCount]);
            car.name = @"奥迪";
            car.weight = @1000;
    
            Car *car2=[car copy];
           // NSLog(@"car2 retaincount is %lu",[car2 retainCount]);
            NSLog(@"car %@,car2:%@",car.engine,car2.engine);
    


    输出结果:

    car ,car2:

    可以看出浅复制只是复制指针,并没有创建新的内存空间

    第二、深拷贝:

    - (id)copyWithZone:(NSZone *)zone {
        /***浅拷贝**/
        Car *car=[[[self class] allocWithZone:zone] init];
        Engine *engineCopy=[[_engine copy] autorelease];
        car.engine=engineCopy;
        
        NSString *namecopy=[[_name copy] autorelease];
        car.name=namecopy;
        
        NSNumber *weightcopy=[[_weight copy] autorelease];
        car.weight=weightcopy;
        return car;
    }
    


    测试代码:

    Car *car = [[Car alloc] init];
            Engine *engine = [[Engine alloc] init];
            car.engine = engine;
            [engine release];
            //NSLog(@"engine retaincount is %lu",[engine retainCount]);
            car.name = @"奥迪";
            car.weight = @1000;
    
            Car *car2=[car copy];
           // NSLog(@"car2 retaincount is %lu",[car2 retainCount]);
            NSLog(@"car %@,car2:%@",car.engine,car2.engine);
    


    结果:

    car ,car2:

    开辟了新的空间,zone代表一块内存空间

     Car *car=[[[self class] allocWithZone:zone] init];
    


    注意上述代码用的是【self class】,而不是car,因为如果是用car,那么car的子类在调用此方法去实现copy协议时,就会出现内存问题

    另外,当子类继承了父类时,他继承了父类的一切属性,包括要实现的协议

    第三、NSFoundation,当我们copy的时一个不可变对象时,默认的copy都是浅拷贝,相当于retain

            NSArray *array =[NSArray arrayWithObjects:@"one",@"two",@"three", nil];
            NSArray *array1 = [array copy];
            NSLog(@"%p",array);
            NSLog(@"%p",array1);
            NSLog(@"the retaincount is %lu",[array retainCount]);
    


    输出结果:

     

    copyDemo1[673:303] 0x10010a5d0

    2013-12-28 20:01:10.969 copyDemo1[673:303] 0x10010a5d0

    2013-12-28 20:01:10.969 copyDemo1[673:303] the retaincount is 2

    注意retaincount会增加

    当使用mutableCopy时,不管对象是否可变,都会实现深拷贝

     

            NSArray *array =[NSArray arrayWithObjects:@"one",@"two",@"three", nil];
            NSMutableArray *array1 = [array mutableCopy];
            NSLog(@"%p",array);
            NSLog(@"%p",array1);
            NSLog(@"the retaincount is %lu",[array retainCount]);


    结果:

     

    copyDemo1[695:303] 0x10010a5d0

    2013-12-28 20:07:08.570 copyDemo1[695:303] 0x10010b260

    2013-12-28 20:07:08.570 copyDemo1[695:303] the retaincount is 1

    第四、retain相当于两个对象指向同一个指针

     

            NSMutableArray *array1 = [[NSMutableArray alloc] initWithObjects:@"one",@"two",@"three",@"foure", nil];
            NSMutableArray *array2 = [array1 retain];
            [array2 removeLastObject];
            NSLog(@"%@",array1);
            NSLog(@"the retaincount is %ld",array2.retainCount);
    

    结果:

     

    2013-12-28 20:13:02.915 copyDemo1[736:303] (
        one,
        two,
        three
    )
    2013-12-28 20:13:02.917 copyDemo1[736:303] the retaincount is 2
  • 相关阅读:
    最佳牛栏(前缀和+二分)
    分形之城(递归)
    约数之和(两种方法)
    递归实现指数型枚举
    【Luogu P3704】 [SDOI2017]数字表格
    【Luogu P2257】 YY的GCD
    【Luogu P2522】 [HAOI2011]Problem b
    【Luogu P3455】 [POI2007]ZAP-Queries
    【Luogu P3597】 [POI2015]WYC
    【Luogu T145192】 【2020.8.23NOIP模拟赛】最优路线
  • 原文地址:https://www.cnblogs.com/jyq-blog/p/4492111.html
Copyright © 2011-2022 走看看