Objective-C的内存基本管理

在OC中每一个变量都保存着引用计数器,当这个对象的引用计数器为0的时候该对象会被回收。当使用alloc、new或者copy创建一个对象的时候,对象的引用计数器被置为1.

给对象发送一条retain消息,能够使引用计数器+1.

给对象发送一条release消息,能够使引用计数器-1.

当OC被销毁的时候会发送一条dealloc消息(不要直接调用,由系统调用),能够重写dealloc方法。在该方法中释放相关资源。

能够给对象发送retainCount消息获取对象的当前引用计数器。

首先我们新建一个project

接下来将project的设置里面将ARC禁掉

Book.h文件

#import <Foundation/Foundation.h>@interface Book : NSObject@property float price;- (id)initBook:(float)price;@end

Book.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];
}@end

Student.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;@end

Student.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];
}@end

main.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 {//计数器为1Student *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的学生被释放了

@classkeyword

通常引用一个类有两种方法。一种是通过#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];}}

转载于:https://www.cnblogs.com/clnchanpin/p/7069053.html

Objective-C基础笔记(3)OC的内存管理相关推荐

  1. 侯捷C++八部曲笔记(五、内存管理)

    侯捷C++八部曲笔记(五.内存管理) 表达式new.delete 基本用法 array new.array delete replacement new ----------------------- ...

  2. Objective-C基础教程学习笔记(九)内存管理

    每个对象都维护一个保留计数器.对象被创建时,其保留计数器值1:对象被保留时,保留计数器值加1:对象被释放时,保留计数器值减1:当保留计数器值归0时,对象被销毁.在销毁对象时,首先调用对象的deallo ...

  3. 关于OC的内存管理-01

    1.什么是内存管理? 大家都知道手机的内存是有限的,app应用的内存也应该是受限制的,随着app应用的使用会导致内存的占用率增大.当内存占用率达到一种程度时.系统会发出内存警告.这时我们须要把一些不用 ...

  4. 十二:内存简单介绍和OC的内存管理

    一.内存简单介绍 内存结构 1.运行时分配 (1)栈:用户存放程序临时创建的局部变量(先进后出). (2)堆:动态分配内存段. 2.编译器分配 (1)BSS段:存放未初始化的全局变量和静态变量. (2 ...

  5. C++学习笔记-DLL中动态内存管理

    动态内存管理 在dll中malloc的内存,必须在dll中free 注:这是由Windows自己的特点决定! 如果 a 编译成静态库,有下面两种解决方法: 1.b.dll 和 c.dll 使用同一个款 ...

  6. c#基础(一)之内存管理

    1.内存管理 c#编程的一个优点是程序员不需要关心具体的内存管理,尤其是垃圾收集器会处理所有的内存清理工作.虽然不必手工管理内存,但如果要编写高质量的代码,还是要理解后台发生的事情,理解c#的内存管理 ...

  7. 《现代操作系统(中文第四版)》笔记 第三章 内存管理

    #内存管理 3.1无存储器抽象 最开始并没有对存储器进行抽象,直接简单粗暴的使用物理内存地址,直接从0到某个上限值.每个地址可容纳一定的二进制位存储单元, 通常为8位.这个时期的组织内存的三种方式如下 ...

  8. 嵌入式Linux驱动笔记(二十九)------内存管理之伙伴算法(Buddy)分析

    你好!这里是风筝的博客, 欢迎和我一起交流. 我们知道,在一个通用操作系统里,频繁申请内存释放内存都会出现一个非常著名的内存管理问题:内存碎片. 学过操作系统的都知道,有很多行之有效的方法(比如:记录 ...

  9. WSF操作系统抽象层学习笔记 (一) ---简介和内存管理

    一.简介 WSF(wireless software foundation)是对操作系统的一个简单的封装,提供对操作系统的简单编程,提供简单的系统服务 功能简介: 事件.消息传递和处理. 定时器功能. ...

最新文章

  1. 励研(LY) CRC16算法
  2. php 输出rtf,有没有办法在PHP中访问压缩RTF和输出RTF代码
  3. sqoop导入数据到hive中元数据问题
  4. 使用maven编译YCSB0.1.4对cassandra进行性能测试
  5. 6、WHERE:条件查询数据
  6. workbench设置单元坐标系_ANSYS经典案例在Workbench中实现分享连载(三)
  7. Ext.core.DomHelper 可以透明地操作HTML或者DOM
  8. STM32F429HAL库时钟系统学习笔记
  9. 3个极品在线PDF转换成WORD服务网站,比软件给力!
  10. matlab libsvm支持向量机工具箱安装与使用
  11. html半透明遮罩,div背景半透明 覆盖整个可视区域的遮罩层效果
  12. 腾讯云学生服务器购买教程(图文)
  13. ior - POSIX文件系统测试工具
  14. 2015款java 650b duina_整车推荐:9款5000元级别热销山地车
  15. 当代研究生精神状态:早c晚a?!
  16. java英文面试常见问题归纳
  17. Python准备篇:第三方库管理
  18. Vue中图片加载问题总结
  19. @Inject 注解的使用
  20. 创维E900V22E_卡刷固件及升级说明

热门文章

  1. 计算智能-群智能算法-蚁群算法matlab实现
  2. 罗马数字转整数(C实现)
  3. 党在心中(turtle画图)
  4. ps cs6磨皮插件_【PS插件】ps磨皮插件Portraiture
  5. 贷款承诺(Loan Commitment)
  6. 使用jackson转换类型时报Unrecognized field
  7. vue/cli 3.0 脚手架【进阶】 使用 amfe-flexible 和 postcss-px2rem进行移动端适
  8. 用keras作CNN卷积网络书本分类(书本、非书本)
  9. 数据结构与算法分析:C语言描述(原书第2版 简体中文版!!!) PDF+源代码+习题答案...
  10. Eclipse 中 Maven 项目默认JDK版本为1.5 的解决方法