// // main.m // OC - 内存管理 // // Created by dllo on 16/2/26. // Copyright © 2016年 dllo. All rights reserved. // #import <Foundation/Foundation.h> #import "Person.h" #import <objc/runtime.h> int main(int argc, const char * argv[]) { @autoreleasepool { /**创建一个Peron类, 有三个实例变量, 可见度为公有的, setter和getter方法, 自定义初始化方法和遍历构造器. */ #if 0 Person *person1 = [[Person alloc]init]; //对象内存的是地址, 指向栈区内的内容 person1->_name = @"Tom"; person1->_sex = @"male"; person1->_age = 21; /** 直接显示对象大小需要导入<objc/runtime.h>*/ NSLog(@"size:%ld",class_getInstanceSize([person1 class])); NSLog(@"%d: 对象和实例变量的地址", __LINE__); NSLog(@"person1 add: %p", person1); NSLog(@"person1 name add %p", &person1->_name); NSLog(@"person1 sex add %p", &person1->_sex); NSLog(@"person1 age add %p", &person1->_age); NSLog(@"************"); NSLog(@"%d: 实例变量是对象类型, 指针内容是一个地址.", __LINE__); NSLog(@"person1 name content: %p", person1->_name); NSLog(@"Tom add : %p", @"Tom"); NSLog(@"person1 sex content %p", person1->_sex); NSLog(@"Man add : %p", @"male"); NSLog(@"实例变量不是对象类型"); NSLog(@"person1 age content: %ld", person1->_age); /** 使用person1 创建一个新的Person类对象 */ Person *person2 = person1; NSLog(@"%d: person2对象和实例变量的地址", __LINE__); NSLog(@"person2 add : %p", person2); NSLog(@"person2 name add: %p", &person2->_name); NSLog(@"person2 sex add: %p", &person2->_sex); NSLog(@"person2 age add: %p", &person2->_age); NSLog(@"person2 name content: %p", person2->_name); NSLog(@"tom add : %p", @"Tom"); #pragma mark - alloc 方法 /**开辟内存空间, 内存空间引用数为1 */ Person *per = [[Person alloc]init]; /**retaincount查看对象的引用计数 */ NSLog(@"per: %ld", [per retainCount]); Person *per2 = [[Person alloc]initWithName:@"tom" sex:@"male" age:33]; NSLog(@"per2 : %ld", [per2 retainCount]); Person *per3 = [Person personWithName:@"mafeng" sex:@"male" age:23]; NSLog(@"per3 : %ld", [per3 retainCount]); #pragma mark - retain 方法 /**retain 方法使引用计数加1 */ [per retain]; NSLog(@"per count: %ld", [per retainCount]); [per retain]; NSLog(@"per count: %ld", [per retainCount]); [per2 retain]; NSLog(@"per2 count: %ld", [per2 retainCount]); #pragma mark - release 释放方法 /** release方法使引用计数减一 */ [per release]; NSLog(@"per count: %ld", [per retainCount]); [per release]; NSLog(@"per count: %ld", [per retainCount]); [per release]; NSLog(@"per count: %ld", [per retainCount]); //内部的内存优化, 无需去管 /** 此时per的引用计数为0, 系统会自动调用的dealloc方法, 释放内存 */ /** 通过重写父类的的dealloc 方法验证一下, 详见Person.m文件 */ /** 当引用计数为0时, 系统会释放这块内存 */ /** 在一段代码中引用计数怎加的次数要和减少的次数相等. */ /** 当引用计数为0后, 在对这块内存的引用计数进行减一, 会造成内存过度释放 */ //[per release]; /** 对它进行操作时会造成野指针现象 */ per->_name = @"Mike"; Person *per4 = per2; NSLog(@"per4: %ld", [per4 retainCount]); /** 对象的引用计数为0时, 对象的引用变得无效, 这样的引用通常被称为"dangling pointer"悬挂指针. 所以此时给对象发送消息往往会出现意外, 甚至发生崩溃. 这个时候出现野指针现象, */ /** 内存泄露: 引用计数增加的次数要比减少的次数多, 此时造成内存的泄露 */ /** 重点了解引用计数机制, 当引用计数为0的时候, 系统释放已经开辟的内存, 所以要保证在一段代码中引用计数增加和减少的次数相同 */ #endif #if 1 #pragma mark - autorelease 方法 /** autorelease 不是立即对引用计数减一. 当向一个对象发送autorelease消息的时候, 这个对象会被添加到最近的自动释放池中, 当离开这个自动释放池的时候, 就会为这个对象发送release消息, 引用计数减一 */ Person *per = [[Person alloc]init]; @autoreleasepool { [per retain]; NSLog(@"person count: %ld", [per retainCount]); [per autorelease]; NSLog(@"person count: %ld", [per retainCount]); } NSLog(@"person count: %ld", [per retainCount]); #endif } return 0; }
Person.m
// // Person.m // OC - 内存管理 // // Created by dllo on 16/2/26. // Copyright © 2016年 dllo. All rights reserved. // #import "Person.h" @implementation Person - (void)setName:(NSString *)name{ _name = name; } - (void)setSex:(NSString *)sex{ _sex = sex; } - (void)setAge:(NSInteger)age{ _age = age; } - (NSString *)name{ return _name; } - (NSString *)sex{ return _sex; } - (NSInteger)age{ return _age; } - (instancetype)initWithName:(NSString *)name sex:(NSString *)sex age:(NSInteger)age{ self = [super init]; if (self) { _name = name; _age = age; _sex = sex; } return self; } + (instancetype)personWithName:(NSString *)name sex:(NSString *)sex age:(NSInteger)age{ Person *per = [[Person alloc]initWithName:name sex:sex age:age]; return per; } - (void)dealloc { NSLog(@"%s: %d", __func__, __LINE__); NSLog(@"%@内存被回收",self); [super dealloc]; } @end