OC-内存管理:retain/copy(深、浅拷贝)的使用和区别详解

/*

程序设计目的:分析深拷贝、浅拷贝、retain的使用和区别


注:实验前请关闭ARC

*/

#import <Foundation/Foundation.h>

#import "Person.h"

#import "Dog.h"

int main(int argc,constchar * argv[])

{

    @autoreleasepool {

       //测试:

       //浅拷贝:

       NSLog(@"浅拷贝:");

       NSString *str = [NSStringstringWithFormat:@"%@",@"copy"];

       NSLog(@"str创建之后计数器的值:%li",[str retainCount]);

       NSLog(@"str内存地址 %p",str);


       NSString *string  = [strcopy];

       NSLog(@"str浅拷贝之后计数器的值: %li",[str retainCount]);

       NSLog(@"string的内存地址: %p",string);

       NSLog(@"string的计数器的值:%li",[string retainCount]);

       //深拷贝:

       NSLog(@"深拷贝:");

        NSMutableString *str_1 = [NSMutableStringstringWithFormat:@"Deep Copy"];

       NSLog(@"str_1创建之后计数器的值: %li",[str_1 retainCount]);

       NSLog(@"str_1的内存地址%p",str_1);

        

       NSMutableString *string_1 = [str_1copy];

       NSLog(@"str_1深拷贝之后计数器的值: %li",[str_1 retainCount]);

       NSLog(@"string_1的内存地址: %p",string_1);

       NSLog(@"string_1的计数器的值:%li",[string_1 retainCount]);

        

        //retain:

       NSLog(@"retain:");

       NSString *str_r = [NSStringstringWithFormat:@"retain"];

       NSLog(@"str_r创建之后计数器的值: %li",[str_r retainCount]);

       NSLog(@"str_r的内存地址%p",str_r);


        

        

       NSString *string_r = [str_rretain];

       NSLog(@"str_r retain之后计数器的值: %li",[str_r retainCount]);

       NSLog(@"string_r的内存地址: %p",string_r);

       NSLog(@"string_r的计数器的值:%li",[string_r retainCount]);

        

       //测试结果:

        

       /*

         输出结果:

         2014-11-16 16:12:15.922 Ram_control[1400:303]浅拷贝:

         2014-11-16 16:12:15.924 Ram_control[1400:303] str创建之后计数器的值:1

         2014-11-16 16:12:15.924 Ram_control[1400:303] str内存地址 0x100200c10

         2014-11-16 16:12:15.925 Ram_control[1400:303] str浅拷贝之后计数器的值: 2

         2014-11-16 16:12:15.925 Ram_control[1400:303] string的内存地址: 0x100200c10

         2014-11-16 16:12:15.925 Ram_control[1400:303] string的计数器的值:2

         2014-11-16 16:12:15.926 Ram_control[1400:303]深拷贝:

         2014-11-16 16:12:15.926 Ram_control[1400:303] str_1创建之后计数器的值: 1

         2014-11-16 16:12:15.927 Ram_control[1400:303] str_1的内存地址0x1005001d0

         2014-11-16 16:12:15.927 Ram_control[1400:303] str_1深拷贝之后计数器的值: 1

         2014-11-16 16:12:15.927 Ram_control[1400:303] string_1的内存地址: 0x100500180

         2014-11-16 16:12:15.928 Ram_control[1400:303] string_1的计数器的值:1

         2014-11-16 16:12:15.928 Ram_control[1400:303] retain:

         2014-11-16 16:12:15.928 Ram_control[1400:303] str_r创建之后计数器的值: 1

         2014-11-16 16:12:15.929 Ram_control[1400:303] str_r的内存地址0x100300b80

         2014-11-16 16:12:15.929 Ram_control[1400:303] str_r retain之后计数器的值: 2

         2014-11-16 16:12:15.930 Ram_control[1400:303] string_r的内存地址: 0x100300b80

         2014-11-16 16:12:15.931 Ram_control[1400:303] string_r的计数器的值:2

         */

       /*

         注:关于本博客中讨论内存管理的章节,都是在关闭ARC模式下运行的,否则程序报错。

         

         

         浅拷贝总结:

         浅拷贝是对不可变对象的复制,

         从上面的测试可以看出,浅拷贝只是简单的使新指针指向对象,对象永远只有一个!从结果可以看到拷贝前后,指针所指向的内存地址没有改变,还是原来那个对象(str所指向的对象)的地址。浅拷贝的结果仅仅是对象的引用计数器自增1而已.

         深拷贝总结:

         深拷贝是对可变对象的真复制,

         从上面的结果看出,深拷贝是对对象的拷贝,结果中显示原来的对象(str_1所指向的对象)的引用计数的值拷贝前后没有增减,指针string_1所指向的内存地址也不再是原来的地址,而且string_1所指向的对象的引用计数也是1,所以深拷贝是重新创一个新对象,但是却保留原来对象的值(原来对象的值是“deepcopy”);

         retain:结果和浅拷贝一样,仅仅是使得对象的引用计数器自增1.但是他们难道就没什么区别吗,有,

         1.retain可以对可变对象和不可变对象同时操作(对可变对象操作却不可能实现和copy一样结果),所以接收返回值的类型需要与使用retain的对象保持一致。

         2.就是下边要讲的自定义copy,自定义copy需要实现一些协议,有些赘余,而retain这没有这方面的要求,如果不是必须最好使用retain


retain的使用在数组和字典中。当数组或字典把id对象存入是,就是retain的操作。


         */

   

       //自定义拷贝:接收copy消息的对象不是OC的基本类型(例如:NSStringNSArray等)而是自己定义的类。

       /*随便在一个自定义类中加入下面1.2.3.三段代码都可以实现自定义拷贝

         1.person类(这个类可以是任何一个自定义的类)的头文件中声明使用NSCopying协议,

            @interface Person : NSObject<NSCopying>

         {

            NSString *_name

         }

         2.person类的.m文件中实现NSCopying协议,把需要的操作写在方法中:

         -(id)copyWithZone:(NSZone *)zone{

            Person *man = [[[self class] allocWithZone:zone] init];

         

            //我们希望copy的内容(或者说希望的操作)都在这实现。

            man.name = self.name;

         

            return man;

         }

         3.在复写的dealloc中还要把copy的对象release

         -(oneway void)dealloc{

            [_name release];

            [super dealloc];

         }

         */

        

       Person *man = [PersonpersonWithName:@"Bieber"];

       Person *woman = [mancopy];

       NSLog(@"man:%@",man.name);

       NSLog(@"woman:%@",woman.name);

       /*结果:

         2014-11-16 17:12:45.337 Ram_control[1586:303] man:Bieber

         2014-11-16 17:12:45.337 Ram_control[1586:303] woman:Bieber

         */

    }

   return0;

}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值