Object-C的内存管理和.NET有些不一样,.NET的内存回收机制是使用GC自动处理回收,而Object-C本质上还是C语言,所以很多时候还是需要手动去管理内存回收。

  1. Object-C生成一个对象

    Engine *en=[[Engine alloc] init];

    [en dealloc];

    Object-C对象生成分配空间在堆上,需要使用指针来指向其引用。前面也说到了,Object-C中得对象其实就是C中的指针。

  2. 对象初始化以及销毁方法

    +(id) alloc; 注意这里的alloc是一个类方法,调用alloc方法之后会在内存中分配一块空间,并且引用计数会设置为1

    +(id) init; 调用init方法表示初始化对象

    -(void) dealloc; 这里注意一下dealloc不是一个类方法,而是一个实例方法。dealloc 方法用于销毁对象,当引用计数为0的时候系统会自动调用dealloc方法销毁对象

    -(void) release; 调用这个方法用于释放对象的引用,引用计数会-1

    -(void) retain ;调用这个方法用于将引用计数+1

    - (NSUInteger)retainCount; 用于获取一个对象当前被多少对象拥有

  3. 叫苦不迭的内存泄露

    实例一:

Engine *en=[[Engine alloc] init];
Engine *en2=en;
[en print];
[en dealloc];
[en2 print];
[en2 dealloc];

实例一 代码

    [en print]; 这段代码能够正确的输出数据;[en2 print] 和 [en2 dealloc] 方法则不能正常执行。因为en,en2 指针都指向了同一个对象引用,而[en dealloc]调用释放了这个对象。当en2 调用print 和 dealloc的时候,该对象已经不存在了。

    实例二:

Engine *en=[[Engine alloc] init];
Engine *en2=en;
[en print];
[en release];
[en2 print];
[en2 release];
[en release];

实例二 代码

    [en print]这段代码能够正常的输出数据,而[en2 print]仍然不能正常执行。为什么?当调用[[Engine alloc ] init] 的时候,en 指针指向这个对象,这个时候retainCount=1 。

    Engine *en2=en 这个时候将指针en2也指向这个对象,retainCount=1;

    当en调用release方法的时候,retainCount 数量-1,retainCount=0; 这个时候系统会自动调用dealloc方法,自动回收对象。所以当下面再次调用的时候则不能正常执行。

    实例三:

Engine *en=[[Engine alloc] init];
Engine *en2=en;
[en2 retain];
[en print];
[en release];
[en2 print];
[en2 release];

实例三 代码

    这段代码和上面一段代码的区别在于调用了[en2 retain]. 在Object-C中retainCount不会自动增加,需要调用retain才会增加。所以当调用[en2 retain]之后retainCount=2. 即使后面调用了[en release],retainCount仍然为1,对象不会去销毁。所以下面会正常执行。如果不调用[en2 release]那么retainCount会始终等于1,对象不会得到释放就会发生内存泄露。

  4. 内存自动回收处理

   上面的处理的确有点太麻烦了,内存管理简直就是噩梦。只要稍微不注意就内存泄露了。现在还有更好的一种方式解决以上问题,那就是autorelease pool(自动释放对象池)。使用自动释放对象池,在某些情况一下可以不用手工去处理对象内存的释放,貌似和.NET中的垃圾回收机制有点类似了,但是我们不要完全的依赖与它,这和自动管理内存还是有一定差距的。

Engine *en=[[[Engine alloc] int] autorelease];
Engine *en2=en;
[en2 retain];
[en print];
//[en release];
[en2 print];
[en2 release];

自动释放对象池

  看到上面的代码,en 并没有显示去调用release方法。而autorelase pool 就是有这样的一个好处。

  5. 自动回收原理简介

  要使用自动回收我们必须手工创建自动释放对象池,NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

  NSAutoreleasePool内部包含一个数组(NSMutableArray),用来保存声明为autorelease的所有对象。如果一个对象声明为autorelease,系统所做的工作就是把这个对象加入到这个数组中去。当NSAutoreleasePool自身释放的时候,会遍历数组中的所有对象,并且调用release方法。如果对象的retainCount=0 那么系统会释放这些对象,如果retainCount>0,则会内存泄露。

  在某些情况下,NSAutoreleasePool 调用的销毁方法比较迟,这个时候会占用大量的内存,我们也可以使用内嵌的方式,创建多个NSAutorelease的实例,让占用的资源立马释放掉。

Object C学习笔记4-内存管理的更多相关文章

  1. linux kernel学习笔记-5内存管理_转

    void * kmalloc(size_t size, gfp_t gfp_mask); kmalloc()第一个参数是要分配的块的大小,第一个参数为分配标志,用于控制kmalloc()的行为. km ...

  2. XV6学习笔记(2) :内存管理

    XV6学习笔记(2) :内存管理 在学习笔记1中,完成了对于pc启动和加载的过程.目前已经可以开始在c语言代码中运行了,而当前已经开启了分页模式,不过是两个4mb的大的内存页,而没有开启小的内存页.接 ...

  3. COCOS学习笔记--Cocod2dx内存管理(三)-Coco2d-x内存执行原理

    通过上两篇博客.我们对Cocos引用计数和Ref类.PoolManager类以及AutoreleasePool类已有所了解,那么接下来就通过举栗子来进一步看看Coco2d-x内存执行原理是如何的. / ...

  4. Cocos2D-X2.2.3学习笔记3(内存管理)

    本章节介绍例如以下: 1.C/C++内存管理机制 2.引用计数机制 3.自己主动释放机制 1.C/C++内存管理机制 相信仅仅要懂oop的都知道NEW这个keyword吧,这个通俗点说事实上就是创建对 ...

  5. 《C#高级编程》学习笔记----c#内存管理--栈VS堆

    本文转载自Netprawn,原文英文版地址 尽管在.net framework中我们不太需要关注内存管理和垃圾回收这方面的问题,但是出于提高我们应用程序性能的目的,在我们的脑子里还是需要有这方面的意识 ...

  6. Cocos2d-x 学习笔记(7) 内存管理 Sprite SpriteFrame Texture2D

    1. 总结 Sprite和SpriteFrame和Texture2D关系紧密,三个类都继承了Ref类.精灵有成员精灵帧和纹理,精灵帧有成员纹理.精灵帧和纹理被精灵帧引用时,引用计数增加,不再被引用时, ...

  7. 嵌入式linux学习笔记1—内存管理MMU之虚拟地址到物理地址的转化

    一.内存管理基本知识 1.S3C2440最多会用到两级页表:以段的方式进行转换时只用到一级页表,以页的方式进行转换时用到两级页表.页的大小有三种:大页(64KB),小页(4KB),极小页(1KB).条 ...

  8. Linux内核学习笔记——内核内存管理方式

    一 页 内核把物理页作为内存管理的基本单位:内存管理单元(MMU)把虚拟地址转换为物理 地址,通常以页为单位进行处理.MMU以页大小为单位来管理系统中的也表. 32位系统:页大小4KB 64位系统:页 ...

  9. ios学习笔记之内存管理

    一,内存管理类型定义      1,基本类型  任何C的类型,eg:      int,short,char,long,long long,struct,enum,union等属于基本类型或结构体   ...

  10. arm-linux学习笔记3-linux内存管理与文件操作

    配置好linux系统之后需要vim配置一下,有助于我们的编程,主要的配置如下 在/etc/vim/vimrc文件中 "显示行号 set number "自动缩进 set autoi ...

随机推荐

  1. 解决Oracle11g密码180天过期,账号锁住的问题

    1.查看用户的proifle是哪个,一般是default: sql>SELECT username,PROFILE FROM dba_users; 2.查看指定概要文件(如default)的密码 ...

  2. 解决 hibernate cannot define positional parameter after any named parameters have been defined

    解决 hibernate  cannot define positional parameter after any named parameters have been defined 把模糊查询的 ...

  3. jumpserver 问题,给自己看的哦,你们不准看哟

    给自己看的,排版忽略! http://docs.jumpserver.org/zh/docs/setup_by_centos7.html 看完全部文档后解决不了再看下边的!!! docker 服务启动 ...

  4. Altium制作DC002的PCB封装和3D模型

    Altium制作DC002的PCB封装和3D模型 常用的电源连接器(Dc Power Jack Connector)DC002.DC005等等型号的3D模型在网上很难找到合适的,我们可以选择CUI 公 ...

  5. JavaScript基础之数据类型部分总结

    JavaScript 是世界上最流行的脚本语言,被设计为向 HTML 页面增加交互性. 我把它的基础语法分为了三个部分:数据类型,运算符,流程控制语句.入门还是比较容易的. 基本概念: 标识符:指变量 ...

  6. 超简单,centos7安装docker

    1.在centos7上直接yum安装docker [root@localhost ~]# yum install docker 2.启动docker [root@localhost ~]#servic ...

  7. Day17 多线程编程

    基本概念 进程:内存中正则运行的一个应用程序.一个进程包含多个线程. 线程:进程中的一个执行流程. 多线程:有两个或两个以上的并发执行流程. 线程的声明周期 说明: 1. 新建状态(New)      ...

  8. 模拟器配置Burpsuite抓取https包

    在模拟器中设置代理,长按WiredSSID会弹出菜单: 点击修改网络: 显示高级选项打勾,然后设置代理ip,也就是你运行burp的机器ip: 然后导出burp的证书: 设置保存的路径和文件名: 模拟器 ...

  9. GeeTest 极验验证

    前台Html页面 <script src="http://libs.baidu.com/jquery/1.9.0/jquery.js"></script> ...

  10. sudo: java: command not found

    背景:搭建了jumpserver,给开发划分了所有权限,但是开发那边账户不能执行java命令 报错:sudo: java: command not found 解决方法: 在用户管理权限配置sudoe ...