1、对于面向对象的语言,程序需要不断地创建对象。这些对象都是保存在堆内存中,而我们的指针变量中保存的是这些对象在堆内存中的地址,当该对象使用结束之后,指针变量指向其他对象或者指向nil时,这个对象将称为无用对象,因为没有指针指向它了,这种情况称为内存泄漏。当内存泄漏非常严重时,会导致内存不够用,程序就会崩掉。因此,内存管理是学习面向对象语言中非常重要也是非常头疼的一个问题。在Java、C++、OC等语言中都涉及到这些问题,Java的内存管理是非常轻松的,因为这些内存管理的工作都由虚拟机自动去完成,不需要程序员自己管理,C++就苦逼了,需要程序员时时刻刻注意内存管理,防止内存泄漏。而对于我们学习的OC语言,内存管理已经从最开始需要我们进行手动管理发展倒现在可以自动管理了,尽管现在已经不需要我们过多地关心内存管理问题,但是还是有必要了解一些基本概念和思想,这也是本篇文章的出发点。

2、内存管理其实主要就是两个方面的内容:内存分配和内存回收。

  • 内存分配:当程序创建对象时需要为对象分配内存,采用合理的实际,尽量减少对象的创建,并减少创建过程中的内存开销。一般而言,内存的分配工作相对而言对程序的影响小一些,即使程序在一段时间内创建了过多的对象,造成了较大的内存开销,但是只要这些对象占用的内存得到了及时回收,程序也依然可以正常运行。而且,内存的分配操作相对而言非常简单,当程序创建对象时,系统会自动为这些对象分配内存。
  • 内存回收:当程序不再需要对象时,系统必须及时回收这些对象所占用的内存,以便程序可以再次使用这些内存。相比之下,内存回收操作就复杂得多,管理起来也非常困难。因此,人们开发了多种内存回收机制,典型的回收机制有两种:自动回收(系统自动跟踪对象进行适时回收对象)和混合回收(系统和程序员共同完成回收工作)。

3、在Xcode4.2之前,OC的内存回收需要程序员花费大量的精力去理解内存回收相关的理论知识,并且程序中必须通过retain、release、autorelease等方法去管理对象的引用计数,这样才能让程序正常回收内存。Xcode4.2引入了新特性:自动引用计数(Automatic Reference Counting,ARC),ARC机制将会自动释放对象所占用的内存,通过启用ARC特性,我们不再需要重点关注内存回收相关的内容。

4、程序创建一个对象之后,怎么知道该对象什么时候应该被回收呢?OC中采用的是引用计数的机制来跟踪对象的状态:每个对象都有一个与之关联的整数,这个证书被称之为引用计数。在正常情况下,当一段代码需要使用某个对象时,应将该对象的引用计数加1,当这段代码不再需要该对象时,应该将该对象的引用计数减1,表示这段代码不再访问该对象了。当对象的引用计数为0时,表明没有任何程序需要该对象了,系统就会回收该对象所占用的内存。系统在销毁该对象之前,会自动调用该对象的dealloc方法(该方法继承自NSObject)来执行一些回收操作。如果该对象还持有其他对象的引用,此时必须重写dealloc方法,在该方法中释放该对象所持有的其他对象(通常就是将所持有对象的引用计数减1)。

  • 手动引用计数回收的标准就是:当一个对象的引用计数为0时,就表明程序不再需要该对象了,从而通知系统回收该对象所占用的内存,系统调用dealloc方法执行回收操作,然后销毁该对象。手动引用计数的难点就说程序员要保证每个对象具有正确的引用计数。
  • 程序员千万不要主动地去掉用对象的dealloc方法!当一个对象的引用计数为0 时,系统会自动取调用该对象的这个方法。
  • 当对象被销毁之后,此时该对象已经不存在,如果有一个指针指向这个被销毁的对象,这个指针就被称为悬空指针,调用悬空指针指向对象的方法时,程序会出现未知结果,甚至导致程序崩溃。

5、在手动引用计数中,改变对象引用计数的方式如下:

  • 当程序员调用方法以alloc、new、copy、mutableCopy开头的方法来创建对象时,该对象的引用计数加1.(方法名一定要是驼峰格式才可以)
  • 程序员调用retain方法时,该对象引用计数加1.
  • 程序员调用release方法时,该对象的引用计数减1.

  NSObject中提供了有关引用计数的如下方法:

  • - retain:该对象引用计数加1.
  • - release:该对象的引用计数减1.
  • - autuorelease:不改变该对象引用计数的值,只是将该对象放入到自动释放池中
  • - retainCount:返回该对象的引用计数的值
     Person *person = [[Person alloc] init];//引用计数为1
    NSLog(@"引用计数:%ld",[person retainCount]); //引用计数加1,为2
    [person retain];
    //引用计数减1,为1
    [person release]; //打印结果是1
    NSLog(@"引用计数:%ld",[person retainCount]);
    //再次释放后引用计数减1,为0 ,系统将自动销毁对象
    [person release];

5、手动引用计数的基本思路就是谁(包括对象、函数等)把对象的引用计数加1,谁就要负责在“临死”前把该对象的引用计数减1,也就是说任何实体(包括对象、函数)在结束签都应该把其他对象的引用计数回复到开始前的状态。从这个角度来看,如果一个函数方法中返回一个对象,那么这个对象在方法结束后由于计数减1为0会被销毁,无法有效地将有效的指针对象返回给调用者,但是如果不按照上面的思路则又破坏了手动引用计数的基本原则。因此,我们需要一种有效而又优雅的解决方案——自动释放池。

  所谓自动释放池(OC中有一个专门管理的类NSAutoreleasePool),就说一个存放对象的容器(比喻集合),自动释放池会保证延迟释放该池中所有的对象。所谓的自动释放,其实只是依次调用池中的每一个对象的release方法,将池中所有对象的引用计数减1.那么什么时候会自动释放呢?其实自动释放池(NSAutoreleasePool)的本质是采用MSMutableArray集合作为容器,当把对象添加到池中时实际上是把这些对象添加到MSMutableArray集合中,然后程序重写了MSMutableArray的release方法,并在该方法中依次调用容器中的每个对象的release方法。所以,当自动释放池(NSAutoreleasePool对象)调用release方法时我们加入自动释放池中的对象也就进行了释放。

  如何将一个对象加入自动释放池呢?在前面第四点的时候降到了NSObject方法中有一个autorelease方法,任何对象调用该方法就可以将该对象加入到自动释放池中。

6、临时对象:对于Foundation中的类而言,当调用方法创建对象时,只要不是以alloc、new、copy、mutableCopy开头的方法创建出来的对象,系统就会默认创建自动释放的对象,这些对象称之为临时对象。

7、手动内存管理的规则总结如下:

  • 调用对象的release方法并不是销毁该对象,只是将该对象的引用计数减1,当一个对象的引用计数为0时,系统会自动调用该对象的dealloc方法来销毁该对象。
  • 当自动释放池被回收时,自动释放池会依次调用该池中的每一个对象的release方法。如果该对象调用release方法后引用计数为0 ,那么该对象将被回收,否则该对象可以从自动释放池中活过来。
  • 当程序使用alloc、new、copy、mutableCopy开头的方法创建对象后,该对象的引用计数为1,当不再使用该对象时,需要调用该对象的release或autorelease方法
  • 如果使用retain方法为对象增加过引用计数,则用完该对象后需要调用release方法来减少该对象的引用计数,并保证retain次数和release次数相等。
  • 如果通过其他方式获取了对象,且对象是一个临时对象,若是在自动释放池上下文中使用该对象,那么使用完成之后无需理会对象的回收,系统会自动回收该对象。如果程序需要保留该临时对象,可以手动调用retain方法来增加该对象的引用计数,或者将该临时对象赋值给retain、strong或copy指示修饰符的属性。
  • 在Cocoa或IOS的事件循环中,在每个事件处理方法执行之前会创建自动释放池,方法执行完后曾之后会回收自动释放池。

8、在IOS 5 引入ARC之后,OC编程就不再需要过多地关注内存管理这一块的内容了。对于IOS开发者而言,最新的Xcode在创建IOS项目时已经默认已经开启ARC机制了,当然,你也可以通过项目属性选择关闭或开启ARC。"Building Setting"---> “Language Objective C” ---> "Objective - C Automatic Reference Counting"

9、现在最新的Xcode在代码中基本上会自动定义@autoreleasepool块,这其实就是自动释放池的上下文,任何在该上下文中创建的对象都由喜用的ARC来自动进行管理释放,并在释放结束后消除这些对象。合理使用@autoreleasepool相当于创建了一层自动释放区域:所有在@autoreleasepool范围内创建的变量,都会在@autoreleasepool结束时执行一次release,这样就可以保证这些对象在@autoreleasepool释放时获得提前释放的机会,从而降低了内存的占用率。

10、在正常情况下,如果某个函数很长,且在该函数运行过程过程中出现很多中间变量,占据了大量的内存,或者程序在执行过程中创建了大量的临时对象(比喻在循环中创建对象),程序可能需要多次释放这些临时对象,这次程序可以考虑将@autoreleasepool块放在循环体内。

 for(int i =  ; i <  ; i++)
{
@@autoreleasepool{
//创建临时对象
//调用临时对象的方法
。。。
}
}

OC学习10——内存管理的更多相关文章

  1. java虚拟机学习-JVM内存管理:深入垃圾收集器与内存分配策略(4)

    Java与C++之间有一堵由内存动态分配和垃圾收集技术所围成的高墙,墙外面的人想进去,墙里面的人却想出来. 概述: 说起垃圾收集(Garbage Collection,下文简称GC),大部分人都把这项 ...

  2. java虚拟机学习-JVM内存管理:深入Java内存区域与OOM(3)

    概述 Java与C++之间有一堵由内存动态分配和垃圾收集技术所围成的高墙,墙外面的人想进去,墙里面的人却想出来. 对于从事C.C++程序开发的开发人员来说,在内存管理领域,他们即是拥有最高权力的皇帝又 ...

  3. python学习Day9 内存管理

    复习 :文件处理 1. 操作文件的三步骤:-- 打开文件:此时该文件在硬盘的空间被操作系统持有 |  文件对象被应用程序持用 -- 操作文件:读写操作 -- 释放文件:释放操作系统对文件在硬盘间的持有 ...

  4. iOS学习之内存管理

    1.1 引用计数 Reference Count 1.2 自动引用计数,ARC(Automatic Reference Counting) 1引用计数 引用计数(Reference Count)是一个 ...

  5. OC开发系列-内存管理

    概述 移动设备的内存极其有限,每个app所有占用的内存是有限的.当app所占用的内存比较多时,系统会发出内存警告,这时得回收一些不需要再使用的内存空间. 任何集成了NSObject的对象都需要手动进行 ...

  6. RT-Thread学习2 —— 内存管理学习记录

    RT-Thread学习2 -- 内存管理学习记录1 小内存管理算法(mem.c) 1. 小内存管理法: 小内存管理算法是一个简单的内存分配算法.初始时,它是一块大的内存.当需要分配内存块时,将从这个大 ...

  7. OC修饰词 - 内存管理

    <招聘一个靠谱的 iOS>—参考答案(上) 说明:面试题来源是微博@我就叫Sunny怎么了的这篇博文:<招聘一个靠谱的 iOS>,其中共55题,除第一题为纠错题外,其他54道均 ...

  8. 深入学习python内存管理

    深入Python的内存管理   作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 语言的内存管理是语言设计的一个重要方面.它是决定语 ...

  9. OC中的内存管理

    一. 基本原理 1. 什么是内存管理 移动设备的内存极其有限,每个app所能占用的内存是有限制的 当app所占用的内存较多时,系统会发出内存警告,这时得回收一些不需要再使用的内存空间.比如回收一些不需 ...

随机推荐

  1. JavaScript学习笔记(八)——变量的作用域与解构赋值

    在学习廖雪峰前辈的JavaScript教程中,遇到了一些需要注意的点,因此作为学习笔记列出来,提醒自己注意! 如果大家有需要,欢迎访问前辈的博客https://www.liaoxuefeng.com/ ...

  2. Fedora 23建立wifi热点(Android手机可用)

    在ubuntu14.04下使用ap-hotspot,速度还不错.但是在15.04下就用不了了,不知为啥.现在使用fedora23,在学校还是挺需要给手机连wifi的,于是google看看ap-hots ...

  3. 如何实现MDI窗体不重复打开同一个子窗体?

    使用MDI窗体时,默认是可以多次打开同一个子窗体的,那么如何控制不重复打开同一个子窗体呢?MDI窗体有个重要属性——MdiChildren,该属性表示MDI窗体打开的子窗体的数组,循环遍历该数组,可以 ...

  4. tcp并发服务器(c20w)

    ** 原创文章,请勿转载 ** 并发服务器是一个老生常谈的话题,今天这里也写一个. 1. 目标: 同时在线连接20万(c20w). 开发语言:重要的事情说三遍,GOLANG, GOLANG, GOLA ...

  5. windows下安装和redis主从配置(通过哨兵控制主从切换)

    首先自己先得了解什么是redis,这里就不详做介绍什么是redis了,这篇文章主要讲的是怎么样配置 redis怎样配置主从关系和哨兵控制主从服务器的配置以及应用,就当是给自己记笔记吧! 1.下载red ...

  6. 重要:关于PPT转图片需要注意的问题

    关于PPT转图片的问题需要注意的问题   我们有一个项目做过直接上传ppt的功能,但是网页不可能显示ppt,所以只能把ppt转成pdf或者图片来显示,我们的做法是转成了图片,然后使用swiper做成类 ...

  7. CSS以图换字的9种方法

    前面的话 CSS以图换字的技术,很久都没人提起了.它是一种在h1标签内,使用图像替换文本元素的技术,使页面在设计和可访问性之间达到平衡.本文将详细介绍CSS以图换字的9种方法 文字隐藏 在h1标签中, ...

  8. Swarm 如何存储数据?- 每天5分钟玩转 Docker 容器技术(103)

    service 的容器副本会 scale up/down,会 failover,会在不同的主机上创建和销毁,这就引出一个问题,如果 service 有要管理的数据,那么这些数据应该如何存放呢? 选项一 ...

  9. (译)ABP之依赖注入

    原文地址:https://aspnetboilerplate.com/Pages/Documents/Dependency-Injection 什么是依赖注入 传统方式的问题 解决方案 构造函数注入 ...

  10. 解决zabbix中文显示乱码问题

    中文显示问题,图表乱码 解决办法: [root@zabbix ~]# cd /usr/share/zabbix/include/ [root@zabbix include]# vim locales. ...