Objective-C基础笔记(3)OC的内存管理
来源:互联网 发布:改之理 源码 编辑:程序博客网 时间:2024/05/17 00:53
Objective-C的内存基本管理
在OC中每个变量都保存着引用计数器,当这个对象的引用计数器为0的时候该对象会被回收。当使用alloc、new或者copy创建一个对象的时候,对象的引用计数器被置为1.
给对象发送一条retain消息,可以使引用计数器+1.
给对象发送一条release消息,可以使引用计数器-1.
当OC被销毁的时候会发送一条dealloc消息(不要直接调用,由系统调用),可以重写dealloc方法,在该方法中释放相关资源。
可以给对象发送retainCount消息获取对象的当前引用计数器。
首先我们新建一个工程
接下来将工程的设置里面将ARC禁掉
Book.h文件
#import <Foundation/Foundation.h>@interface Book : NSObject@property float price;- (id)initBook:(float)price;@endBook.m文件
#import "Book.h"@implementation Book@synthesize price = _price;//构造函数- (id)initBook:(float)price { if(self = [super init]){ _price = price; } NSLog(@"价格是%f的书购买了", _price); return self;}//析构函数- (void)dealloc { NSLog(@"价格为%f的书被释放了", _price); [super dealloc];}@endStudent.h文件
#import <Foundation/Foundation.h>#import "Book.h"@interface Student : NSObject@property int age;@property Book *book;- (void)setBook:(Book *)book;- (id)initStudent:(int)age;@endStudent.m文件
#import "Student.h"#import "Book.h"@implementation Student@synthesize age = _age;@synthesize book = _book;- (void)setBook:(Book *)book { if(_book != book){ //先对原来的书计数器减一 //如果之前为nil不会出错(和java中的空指针不同) [_book release]; [book retain]; _book = book; }}//构造函数- (id)initStudent:(int)age { if(self = [super init]) { _age = age; } NSLog(@"年龄为%d的学生被创建了", _age); return self;}//析构函数- (void)dealloc{ [_book release]; NSLog(@"年龄为%d的学生被释放了", _age); [super dealloc];}@endmain.m文件
#import <Foundation/Foundation.h>#import "Student.h"#import "Book.h"void buyBook(Student *stu) { Book *book1 = [[Book alloc] initBook:101.5]; //谁创建谁释放 stu.book = book1; [book1 release]; Book *book2 = [[Book alloc] initBook:98.5]; stu.book = book2; [book2 release];}void readBook(Student *stu) { NSLog(@"年龄是%i的学生在读价格为%f的书", stu.age, stu.book.price);}int main(int argc, const char * argv[]) { @autoreleasepool { //计数器为1 Student *stu = [[Student alloc] initStudent:21]; //买书 buyBook(stu); //看书 readBook(stu); //计数器清0,释放内存 [stu release]; } return 0;}输出结果:
2014-11-13 23:11:19.510 内存管理[698:46519] 年龄为21的学生被创建了
2014-11-13 23:11:19.512 内存管理[698:46519] 价格是101.500000的书购买了
2014-11-13 23:11:19.512 内存管理[698:46519] 价格是98.500000的书购买了
2014-11-13 23:11:19.512 内存管理[698:46519] 价格为101.500000的书被释放了
2014-11-13 23:11:19.512 内存管理[698:46519] 年龄是21的学生在读价格为98.500000的书
2014-11-13 23:11:19.512 内存管理[698:46519] 价格为98.500000的书被释放了
2014-11-13 23:11:19.512 内存管理[698:46519] 年龄为21的学生被释放了
@class关键字
通常引用一个类有两种方法,一种是通过#import,另一种是通过@class.#import 的方式会将头文件中的所有信息引入。
@class 的方式只是说明它是一个类(假如只是声明一个类就不用使用#import).
#import <Foundation/Foundation.h>@class Book; //声明Book是一个类@interface Student : NSObject { Book *_book;}@property int age;@property Book *book;- (void)setBook:(Book *)book;- (id)initStudent:(int)age;@end另外,Student.m中的析构函数我们可以做如下修改
//析构函数- (void)dealloc{ self.book = nil; //调用setter方法 [_book release]; NSLog(@"年龄为%d的学生被释放了", _age); [super dealloc];}self.book = nil; 会调用setter方法,释放对象并将当前类Student的属性_book设为nil.
@property的参数
@property的参数格式: @property (参数1, 参数2,...) 类型 名字;参数主要分为4类:
读写属性:readwrite / readonly(是否生成get和set方法)
setter处理: assign / retain / copy (和内存管理相关)
原子性:atomic / nonatomic (这两个和多线程相关)
set和get方法名称相关参数:setter(设置生成的set方法名称)/ getter(设置生成的get方法名称)
改变set和get名称,多是用于BOOL类型的变量
@property (nonatomic, assign, setter = abc:) int height; 设置set方法名称为 abc:
说明:
readonly代表只生成getter方法,默认是readwrite
assing默认(set方法直接赋值),copy是setter方法release旧值,再copy新值
retain 要生成符合内存管理原则的set方法(应用于对象类型)(注意:在dealloc方法中释放属性对象)
atomic(默认),保证getter和setter的原子性,提供多线程安全访问,nonatomic性能高,所以一般是选择nonatomic.
#import <Foundation/Foundation.h>@class Book; //声明Book是一个类@interface Student : NSObject//assign参数代表set方法直接赋值(默认的)//getter方法是指定getter方法的名字@property (nonatomic, assign, getter=getStudentAge) int age;//这里的retain代表:release旧值,retain新值//(注意,基本数据类型不能写retain参数)@property (nonatomic, retain) Book *book;- (void)setBook:(Book *)book;- (id)initStudent:(int)age;@end
#import "Student.h"#import "Book.h"@implementation Student//构造函数- (id)initStudent:(int)age { if(self = [super init]) { _age = age; } NSLog(@"年龄为%d的学生被创建了", _age); return self;}//析构函数- (void)dealloc{ self.book = nil; //调用setter方法 [_book release]; NSLog(@"年龄为%d的学生被释放了", _age); [super dealloc];}@end
自动释放池
自动释放池是OC里面的一种内存自动回收机制,一般可以将一些临时变量添加到自动释放池中,统一回收释放。当自动释放池销毁时,池里的所有对象都会调用一次release方法。OC对象只需要发送一条autorelease消息,就会把这个对象添加到最近的自动释放池中(栈顶的释放池)。autorelease实际上只是把release的调用延迟了,对于每一次autorelease,系统只是把该对象放入当前的autorelease pool中,当该pool被释放时,该pool中的所有对象会调用一次release方法。
#import "Student.h"#import "Book.h"@implementation Student//创建静态方法构造对象+ (id)student { Student *stu = [[[Student alloc] init] autorelease]; return stu;}//创建带参数的静态方法构造对象+ (id)studentWithAge:(int)age { Student *stu = [self student]; stu.age = age; return stu;}//构造函数- (id)initStudent:(int)age { if(self = [super init]) { _age = age; } NSLog(@"年龄为%d的学生被创建了", _age); return self;}//析构函数- (void)dealloc{ self.book = nil; //调用setter方法 [_book release]; NSLog(@"年龄为%d的学生被释放了", _age); [super dealloc];}@end
int main(int argc, const char * argv[]) { //代表创建一个自动释放池 @autoreleasepool { //第一种写法 Student *stu = [[[Student alloc] initStudent:21] autorelease]; Student *stu1 = [[[Student alloc] initStudent:21] autorelease]; } //当括号结束后,池子将被销毁 //如果自动释放池被销毁,池里面的所有对象都会调用release方法 @autoreleasepool { //第二种写法 Student *stu2 = [[Student alloc] initStudent:21]; [stu2 autorelease]; } @autoreleasepool { //第三种写法(推荐) //不用手动释放 Student *stu3 = [Student student]; } return 0;}
注意:
1、如果某个对象调用了多次autorelease方法,则在自动释放池销毁的时候会调用多次release方法进行释放。如下:
@autoreleasepool { Person *p = [[Person alloc] init]; [p autorelease]; [p autorelease]; }p对象会被释放两次。
2、如果嵌套autoreleasepool,那么对象将在调用了autorelease(添加到池子)的每层自动释放池结束的时候调用一次autorelease,如下:
Person *p = [[Person alloc] init]; @autoreleasepool { @autoreleasepool { [p autorelease]; } }对象将在第7行被释放,而下面的情况会出现野指针异常
Person *p = [[Person alloc] init]; @autoreleasepool { [p autorelease]; @autoreleasepool { [p autorelease]; } }
- Objective-C基础笔记(3)OC的内存管理
- Objective-C 学习笔记(2) -- OC的内存管理
- OC学习之Objective-C的内存管理
- 【Objective-C】OC中点语法的内存管理
- 【Objective-C】OC中点语法的内存管理
- Objective-c的内存管理笔记
- 【Objective-C学习-4】OC内存管理
- #Objective - C - OC内存管理总结
- Objective-C内存管理基础
- Objective-C内存管理基础
- Objective-C基础学习笔记(八)-内存管理
- OC基础-零基础学习Objective-C:第六部分.ARC内存管理
- 学习笔记:Objective C 的内存管理(2)----set内存管理
- 学习笔记:Objective C 的内存管理(3)----@class以及Autorelease用法
- 【Objective-C】OC基础
- Objective-C的内存管理
- objective-c的内存管理
- Objective C的内存管理
- 二叉树 前中后序遍历非递归版本 C++实现
- ubuntu 设置IP
- poj2352 树状数组
- C语言和Java中的文件操作对比
- Java网络编程
- Objective-C基础笔记(3)OC的内存管理
- VS2012中C#程序根据UML图自动生成代码
- 二分图匹配问题
- 使用synchronized实现同步代码块
- Camera HAL层代码分析1
- SPIflash
- SeekBar自定义样式
- NYOJ 119 士兵杀敌(三)【ST算法】
- 新人