您的位置:首页 > 大数据 > 人工智能

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

2014-11-16 17:27 381 查看
/*
程序设计目的:分析深拷贝、浅拷贝、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的基本类型(例如:NSString,NSArray等)而是自己定义的类。

/*随便在一个自定义类中加入下面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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐