OC05_内存管理
来源:互联网 发布:淘宝怎么弄全球购图标 编辑:程序博客网 时间:2024/06/18 09:19
(一). 引用计数
main.m
ARC 自动引用计数,Automatic Reference Counting.MRC 手动引用计数,Manual Refernce Counting.内存管理机制:引用计数 retainCount.每个对象都有引用计数.引用计数的作用:标记有多少个指针指向这个内存空间.为什么要标记?为了避免其他指针访问这段内存时出现问题(野指针*访问*).野指针不是问题,野指针的访问才是问题.int main(int argc, const char * argv[]) {引用计数的加法方法.1.alloc.引用计数 +1Person *person = [[Person alloc] init];NSLog(@“%ld”, person.retainCount);
2. retain.引用计数 +1Person *newPerson = person; // 把person的地址给newPerson,此时的引用计数依然为1,如果此时释放内存,就会造成其中一个指针为野指针,为了解决这个问题,用retain.Person *newPerson = [person retain];NSLog(@"%ld, %ld”, newPerson.retainCount, person.retainCount); // 此时newPerson的引用计数为2,因为我们把person的引用计数变成了2,然后用newPerson去指向这个地址,这个地址背后所对应的引用计数为2,注意与下面的copy区分.
3. release.引用计数 -1[person release];[person release]; // 如果内存的引用计数为0,系统会自动调用”.m”文件中的dealloc方法--触发内存销毁的方法(如下,次方法,是默认不写的).
Person.m
#import "Person.h"@implementation Person内存销毁法dealloc(销毁) 和 alloc(开辟) 对应.当引用计数变为0时,自动调用dealloc方法.- (void)dealloc { NSLog(@"对象所在的内存销毁"); [super dealloc];}@end
main.m
此时person已经release了两次(此时release两次newPerson和release两次person是等同效果),我们打印newPerson和person的引用计数.NSLog(@“%ld, %ld”, newPerson.retainCount, person.retainCount); return 0;}
其实此时newPerson和person的引用计数已经为0,但是计算机取不到0,它只好打印最接近0之前的状态.
main.m
3.copy.Person *ppp = [[Person alloc] init];NSLog(@"ppp的引用计数为:%ld", ppp.retainCount);Person *newPPP = [ppp copy]; // 复制ppp的内容,然后用一个newPPP来接受ppp的内容,但此时程序会崩溃,所以要在”.m”文件中写入一个拷贝缓冲池来解决拷贝之后:"-[Person copyWithZone:]: unrecognized selector sent to instance 0x10011486"的问题.NSLog(@"再次打印ppp的引用计数为:%ld", ppp.retainCount); // 此时再打印ppp的引用计数,结果并未改变,仍然为1,说明,copy的作用只是复制内容.NSLog(@"newPPP的引用计数为:%ld", newPPP.retainCount); // 此时打印newPPP的引用计数,结果为1,说明,copy之后的内容被newPPP接受了.[ppp retain];NSLog(@"再次打印ppp的引用计数为:%ld", ppp.retainCount); // 将ppp的引用计数再次retain,然后打印.
Person.m
- (id)copyWithZone:(NSZone *)zone { // zone 拷贝缓冲池. // 作用: 确保两个对象的信息除地址之外其它都一样. Person *p = [[Person allocWithZone:zone] init]; p.name = self.name; p.age = self.age; return p; }
(二). 自动释放
main.m
自动释放池,autoReleasePool@autorelease { Person *ppp = [[Person alloc] init]; [ppp retain]; [ppp retain];相当于给ppp做了一个标记,延迟了它的释放时间. [ppp autorelease]; NSLog(@"%ld", ppp.retainCount); [ppp autorelease]; NSLog(@"%ld", ppp.retainCount); [ppp autorelease]; NSLog(@"%ld", ppp.retainCount); } return 0;}
当程序运行至autoreleasepool时,必须等程序执行到括号外面之后,ppp才释放内存.
(三). 内存管理的原则
main.m
int main(int argc, const char * argv[]) {1.当看到alloc, retain, copy的时候, 需要对应的内存管理,哪个对象对应+1,就对哪个对象进行release(autorelease);2.看不到,则不管.Person *person1 = [[Person alloc] init]; // 创建一个person1对象.Person *person2 = [person1 retain]; // 使person1的引用计数加一,用person2来接收它.Person *person3 = [person2 retain]; // 使person2的引用计数加一,用person3来接收它.Person *person4 = [person3 copy]; // 复制person3的内容,用person4来接收它.Person *person5 = person4; // 将person4的内容给person5.NSLog(@"person1的引用计数为:%ld", person1.retainCount);NSLog(@"person4的引用计数为:%ld", person4.retainCount);NSLog(@"person5的引用计数为:%ld", person5.retainCount);
[person1 release];[person2 release];[person3 release];[person4 release]; return 0;}
第一次触发dealloc方法是将person1内存释放.
第二次触发dealloc方法是将person4内存释放.
剩下的person5,变成了野指针.
(四). 如何用自动释放池,管理便利构造器.
在Person.h文件中添加两个属性,自定义初始化,便利构造器.
#import <Foundation/Foundation.h>@interface Person : NSObject<NSCopying>@property(nonatomic, retain)NSString *name;@property(nonatomic, assign)NSInteger age;- (instancetype)initWithName:(NSString *)name age:(NSInteger)age;+ (instancetype)personWithName:(NSString *)name age:(NSInteger)age;@end
Person.m
#import "Person.h"@implementation Person- (instancetype)initWithName:(NSString *)name age:(NSInteger)age { self = [super init]; if (self) { _name = name; _age = age; } return self;}+ (instancetype)personWithName:(NSString *)name age:(NSInteger)age {// 在便利构造器中创建一个person对象,并加入自动释放池(以下是三种释放内存的写法.)(1).Person *person = [[Person alloc] initWithName:name age:age]; [person autorelease];return person;(2). Person *person = [[Person alloc] initWithName:name age:age];return [person autorelease];(3). return [[[Person alloc] initWithName:name age:age] autorelease];}@end
main.m
@autoreleasepool { // 在自动释放池中用一个Person类调用便利构造器方法,并打印对象p的name属性. Person *p = [Person personWithName:@"哈哈" age:100 ]; NSLog(@"%@", p.name);}
Person.m
#import "Person.h"@implementation Person没有在".h"中声明,直接在".m"中写的方法实现,此方法为私有方法,只能在".m"中使用.- (void)sayHi { NSLog(@"你好!~");}用一个方法A,在A方法中调用该私有方法 - (void)sayHi 方法(此A方法省略在”.h”中的声明过程,只写在”.m”中的实现过程).-(void)A { [self sayHi] // 该私有方法为对象方法,所以在便利构造器中调用该私有方法的时候,要先创建一个对象,因为便利构造器是类方法.}@end
0 0
- OC05_内存管理
- OC05_数组
- OC05_数组
- OC05_数组省市区
- 内存管理
- 内存管理
- 内存管理
- 内存管理
- 内存管理
- 内存管理
- 内存管理
- 内存管理
- 内存管理
- 内存管理
- 内存管理
- 内存管理
- 内存管理
- 内存管理
- SQL审核自动化
- c++primer之类(构造函数再探)
- 迭代器模式(五):JDK内置迭代器的使用
- hdoj 3746 Cyclic Nacklace 【kmp(len%(len-p[len])公式的灵活运用)】
- python脚本
- OC05_内存管理
- 【java基础】内存分析
- 开通博客第一天
- Lock
- 【匈牙利算法模板】
- Java的ProtoBuf
- C++ 之 main函数的调用与被调用
- python核心编程-练习2
- 关于伪类元素:before和:after