/*
Objective-c - 内存管理
1> 内存管理概述
内存是用来存储数据的,声明变量就可以将不同类型的数据存储到不同的内存区域当中,以方便管理.存到内存中的数据在不要要的时候应该被释放以保持足够的存储空间而重复利用.
2> 内存中的五大区域
栈区:用来存储局部变量,当作用域执行完毕之后,局部变量会被系统立即释放.
堆区:用来存储oc对象.手动申请的空间需要调用free函数来进行释放.
BSS段:用来存储未初始化的全局变量和静态变量,一旦被初始化就会立即转存到数据段当中去.
数据段:用来存储已经初始化的全局变量,静态变量和常量数据.直到程序结束的时候才会被释放.
代码段:用来存储代码,直到程序结束的时候才会被释放.
3> 在oc中只有堆区中的oc对象需要手动管理,存储在其他区域的数据都会被自动回收或释放.
存储在堆区中的oc对象,是不会自动释放的,如果程序员不主动释放的话,将会一直到程序结束的时候才会被释放.
4> 内存管理的范围.
1,内存管理只需要管理堆区中oc对象的释放.
2,什么时候释放堆区中的oc对象呢?
如果堆区当中的oc对象无人使用的时候,就可以被释放;如果有人在使用这个对象,那么千万不能被释放,否则就会出问题.
3,如何确定oc对象是否有人在使用呢?
引用计数器:每一个oc对象都有一个属性叫做:retainCount(引用计数器).
这个属性的类型是: unsigned long(占据8个字节)
引用计数器的作用:用来统计并表示当前对象有多少个人在使用.
4,引用计数器是如何实现计数的?
在对象在被创建出来的时候,引用计数器的默认值为1.
当这个对象多一个人使用的时候,就让这个对象的引用计数器的值加1,代表多一个人使用.
当这个对象少一个人使用的时候,就让这个对象的引用计数器的值减1,代表少一个人使用.
当这个引用计数器的值为0的时候,代表这个对象无人使用,此时系统便会将这个对象立即回收,在回收这个对象的同时自动调用这个对象的dealloc方法.
5,如何控制对象的引用计数器的值?
为对象发送一条retain消息,那么这个对象的引用计数器的值就会加1;
为对象发送一条release消息,那么这个对象的引用计数器的值就会减1;
为对象发送一条retainCount消息,就可以得到这个对象的引用计数器的值.
5> 内存管理的分类
1,MRC:Manual Reference Countaing (手动引用计数器)
当对象多一个人使用的时候,就为对象发送一条retain消息,使这个对象的引用计数器的值加1;
当对象少一个人使用的时候,就为对象发送一条release消息,使这个对象的引用计数器的值减1;
需要程序员手动的写代码来改变对象的引用计数器的值.
2,在IOS5之后,Xcode6开始,2011年开始出现了ARC自动引用计数器.
ARC:Automatic Reference Countaing (自动引用计数器)
当对象多一个人或者少一个人使用的时候,不需要程序员写代码来改变对象的引用计数器的值,系统会自动的统计对象的引用计数器的值.
6> 内存管理的重点和原则
内存管理的重点:分清楚什么时候应该为对象发送retain消息,什么时候应该为对象发送release消息,以使对象的引用计数器的值加1或者减1.
内存管理的原则:
1,新创建一个对象,这个对象的引用计数器的值是默认值1.有对象的创建就必须为其匹配一个release.
2,谁retain,谁release.retain的次数要和release的次数要匹配.
3,只有当对象多一个人使用的时候,为对象发送retain消息,只有当对象少一个人使用的时候为对象发送release消息.
如下代码:
*/
#import <Foundation/Foundation.h>
//人类的声明
@interface YYPerson : NSObject
{
NSString *_name;
int _age;
}
- (void)setName:(NSString *)name;
- (NSString *)name;
- (void)setAge:(int)age;
- (int)age;
- (void)sayHi;
@end
//人类的实现
@implementation YYPerson
- (void)setName:(NSString *)name
{
_name = name;
}
- (NSString *)name
{
return _name;
}
- (void)setAge:(int)age
{
_age = age;
}
- (int)age
{
return _age;
}
- (void)sayHi
{
NSLog(@"大家好,我叫%@,今年%d岁了!", _name, _age);
}
//重写delloc方法,监视对象的回收.
- (void)dealloc
{
NSLog(@"%@对象释放了!", _name);
[super dealloc];
}
@end
int main(int argc, const char * argv[]) {
//创建对象
YYPerson *xiaoming = [[YYPerson alloc]init];
NSLog(@"xiaoming.retainCount = %lu", xiaoming.retainCount);//xiaoming.retainCount = 1
//赋值属性
xiaoming.name = @"xiaoming";
xiaoming.age = 18;
[xiaoming retain];
NSLog(@"xiaoming.retainCount = %lu", xiaoming.retainCount);//xiaoming.retainCount = 2
//调用方法
[xiaoming sayHi];//大家好,我叫xiaoming,今年18岁了!
[xiaoming retain];
NSLog(@"xiaoming.retainCount = %lu", xiaoming.retainCount);//xiaoming.retainCount = 3
[xiaoming release];
NSLog(@"xiaoming.retainCount = %lu", xiaoming.retainCount);//xiaoming.retainCount = 2
[xiaoming release];
NSLog(@"xiaoming.retainCount = %lu", xiaoming.retainCount);//xiaoming.retainCount = 1
[xiaoming release];//xiaoming对象释放了!
return 0;
}