[黑马程序员]Objective-C 内存管理

引用计数器

每个OC对象都有自己的引用计数器,是一个整数表示对象被引用的次数,即现在有多少东西在使用这个对象。对象刚被创建时,默认计数器值为1,当计数器的值变为0时,则对象销毁。

在每个OC对象内部,都专门有4个字节的存储空间来存储引用计数器。

作用:

判断对象要不要回收的唯一依据就是计数器是否为0,若不为0则存在。

操作:

给对象发送消息,进行相应的计数器操作。

  • Retain消息:使计数器+1,该方法返回对象本身
  • Release消息:使计数器-1(并不代表释放对象)
  • retainCount消息:获得对象当前的引用计数器值

对象的销毁:

当一个对象的引用计数器为0时,那么它将被销毁,其占用的内存被系统回收。

当对象被销毁时,系统会自动向对象发送一条dealloc消息,一般会重写dealloc方法,在这里释放相关的资源,dealloc就像是对象的“临终遗言”。一旦重写了dealloc方法就必须调用[super dealloc],并且放在代码块的最后调用(不能直接调用dealloc方法)。

Person.m:

#import <Person.h>

@implementation Person

- (void) dealloc{
    NSLog(@"Person dealloc...");
    [super dealloc];
}

@end

main.m

#import <Person.h>

int main(){
    // 当我们调用alloc之后,p的引用计数器+1
    Person *p = [[Person alloc] init];
    // 手动调用release方法来对计数器-1,当检测到计数器为0时,就会调用dealloc方法销毁对象
    [p release];

    return 0;
}

相关概念

野指针:

指针指向一个已经被回收的地址。

如上例中,在指向完[p release]之后,p就作为一个野指针存在。

空指针:

没有指向任何东西的指针(存储的东西是0,null,nil),给空指针发送消息不会报错。

如上例中,我们将[p release]改成 p = nil p即为空指针。

原则

1、准则:

  • 只要还有人在使用某个对象,那么这个对象就不会被回收
  • 只要你想使用这个对象,那么就应该让这个对象的引用计数器+1
  • 当你不想使用这个对象时,应该让对象的引用计数器-1

2、谁创建,谁release

如果你通过alloc,new,copy来创建了一个对象,那么你就必须调用release或者autorelease方法。

3、谁retain,谁release

只要你调用了retain,无论这个对象时如何生成的,你都要调用release

4、总结

有始有终,有加就应该有减。曾经让某个对象计数器加1,就应该让其在最后-1。

代码规范

1、只要调用了alloc,就必须有release(autorelease)

2、Set方法的代码规范

(1) 基本数据类型

- (void) setAge: (int) age{
    _age = age;
}

(2) OC对象类型

- (void) setCar: (Car *) car{
    // 判断新设置的对象是否是成员变量里保存的对象
    if(car != _car){
        // 对旧对象进行release
        [_car release];
        // 对新对象进行retain并赋值给成员变量(retain方法返回对象本身)
        _car = [car retain];
    }
}

3、dealloc方法

  • 一定要[super dealloc],而且要放到最后
  • 对self(当前)所拥有的的其他对象做一次release操作

Autorelease

Person *p = [[[Person alloc] init] autorelease];

基本:

  • 会将对象放到一个自动释放池中
  • 当自动释放池被销毁时,会对池子里的所有对象做一次release
  • 会返回对象本身
  • 调用完autorelease方法后,对象的计数器不受影响(销毁时影响)

好处:

  • 不需要再关心对象释放的时间
  • 不需要再关心什么时候调用release

注意:

  • 连续调用多次autorelease,释放池销毁时执行两次release
Person *p = [[[[Person alloc] init] autorelease] autorelease];
  • alloc之后调用了autorelease,之后又调用了release。
Person *p = [[[Person alloc] init] autorelease];
[p release];

自动释放池:

  • 在ios程序运行过程中,会创建无数个池子,这些池子都是以栈结构(先进后出)存在的
  • 当一个对象调用autorelease时,会将这个对象放到位于栈顶的释放池中

自动释放池的创建方式:

  • iOS 5.0以前的创建方式
NSAutoreleasePool *pool=[[NSAutoreleasePool alloc] init];

// ...逻辑代码

[pool  release]; // 在mac中,使用[pool drain]
  • iOS 5.0以后
@autoreleasepool{

    // ...逻辑代码

}

ARC内存管理机制

ARC是Automatic Reference Counting---自动引用计数。

有自动引用计数,那么就得有手动引用计数MRC(Mannul Reference Counting),前面已经提到的就是MRC。

指针类型:

指针分为强指针和弱指针

// 强指针
Person *p = [[[Person alloc] init] autorelease];
// 强指针
__strong Person *p = [[[Person alloc] init] autorelease];
// 弱指针
__weak Person *p = [[[Person alloc] init] autorelease];

也就是说,通过__strong和__week来区分强指针和弱指针,默认情况下,所有指针都是强指针,前面有个__strong

特点:

  • 不允许调用release,retain,retainCount等内存管理方法
  • 允许重写dealloc, 但是不允许调用[super dealloc]
  • 当没有强指针指向这个对象时,这个对象就会被回收
时间: 2024-10-11 10:14:22

[黑马程序员]Objective-C 内存管理的相关文章

黑马程序员——OC的内存管理概述

内存管理在Objective-C中的重要性就像指针在C语言中的重要程序一样. 虽然作为一门高级语言,但OC却没有内存回收机制.这就需要开发者来对动态内存进行管理.OC中内存管理的范围是:任何继承了NSObjective的对象,对基本数据类型是无效的.这和它的管理原理有关. 每个对象内部都保存了一个与之关联的整数,称为引用计数器,当使用alloc.new.或copy创建一个对象时,对象的引用计数器被设置为1.给对象发送一条retain信息,可以使引用计数器的值加1,给对象发送一条release信息

黑马程序员--内存管理(整合修改篇)

今天去看了几篇关于内存管理的文章,写的都是大同小异,但是仔细阅读的话每篇都有或多或少的错误,我对其中的几篇做了个整合,修改了大概一二十处表达或者错误的地方,顺便加了一些自己的理解.当然,又不认同一些内容的请多多指教. OC内存管理 一.基本原理 (一)为什么要进行内存管理. 很多人介绍内存管理时,通常会说“由于内存极其有限,每个app所占的内存也有限制...”.然我我觉的不管是移动还是非移动的,都存在内存管理机制问题,我门只有有效的管理内存,使程序使用最少的内存.保证程序的流畅以及客户端本身的流

黑马程序员——OC的内存管理

1. 基本原理 1. 什么是内存管理 ? 移动设备的内存极其有限,每个app所能占用的内存是有限制的 ? 当app所占用的内存较多时,系统会发出内存警告,这时得回收一些不需要再使用的内存空间.比如回收一些不需要使用的对象.变量等 ? 管理范围:任何继承了NSObject的对象,对其他基本数据类型(int.char.float.double.struct.enum等)无效 2. 对象的基本结构 ? 每个OC对象都有自己的引用计数器,是一个整数,表示“对象被引用的次数”,即有多少人正在使用这个OC对

黑马程序员_ Objective-c 内存管理笔记

引用计数器 当一个对象被创建出来,就要分配给内存这个对象,当不用这个对象的时候,就要及时的回收,为了可以明确知道对象有没有被使用,就要用引用计数器来体现,只要计数器不为0,表明对象被使用中. 1.方法的基本使用 1> retain :计数器+1,会返回对象本身 2> release :计数器-1,没有返回值 3> retainCount :获取当前的计数器 4> dealloc * 当一个对象要被回收的时候,就会调用 * 一定要调用[super dealloc],这句调用要放在最后

Java程序员必备技能内存管理机——垃圾标记

正文 1.怎么找到存活对象? 通过上篇文章我们知道,JVM创建对象时会通过某种方式从内存中划分一块区域进行分配.那么当我们服务器源源不断的接收请求的时候,就会频繁的需要进行内存分配的操作,但是我们服务器的内存确是非常有限的呢!所以对不再使用的内存进行回收再利用就成了JVM肩负的重任了! 那么,摆在JVM面前的问题来了,怎么判断哪些内存不再使用了?怎么合理.高效的进行回收操作?既然要回收,那第一步就是要找到需要回收的对象! 1.1.引用计数法 实现思路:给对象添加一个引用计数器,每当有一个地方引用

黑马程序员——C语言——内存分析

内存分析主要包括以下几部分内容:进制.类型说明符.位运算和关于char类型的一些内容. 一. 进制(二进制.八进制.十进制.十六进制) 1.二进制 ①  特点:只有0和1,逢2进1 ②  书写格式:0b或者0b开头 ③  使用场合:二进制指令\二进制文件,变量在内存中就是二进制存储 ④  二进制和十进制的互相转换 ⑤  n为二进制位所能表示的数据范围(不考虑负数):0~2的n次方-1 2.八进制 ①  特点:0~7,逢八进一 ②  书写格式:0开头 ③  八进制和二进制的互相转换 3. 十六进制

黑马程序员---C语言---内存剖析

------iOS培训.Java培训.Android培训, iOS学习型技术博客,期待与您交流------ 按位与 & 1101110                 101101 0110101                000100 ———————     --------------- 0100100                000100 原位和1&,保持不变:和0&,都为0 因此,可以让原来数字的某位与1&,根据结果能确定该位是0还是1,且结果只有0或1

黑马程序员-OC学习笔记之ARC

---------------------- IOS开发.Android培训.期待与您交流! ----------------------一.什么是ARC        ARC是自动引用计数,苹果官方在Xcode4.2及以后版本中加入的一个内存管理机制,完全取代了程序员人工的内存管理,使得程序员只须关心程序本身.使用ARC,编译器会自动在代码中加入内存管理代码,是一个编译器特性,而不是运行时特性,当然,它也和JAVA的垃圾回收不同,它的本质和手动的内存管理是一样的,只是这些代码编译器会自动添加.

黑马程序员-OC内存管理 @property的增强

涉及到内存管理,只读,多线程等很多功能时,setter和getter方法也就没那么简单了:当然@property依然强大,很好用: 1:内存管理相关参数: *:retain:  (如果是oc对象类型),生成的setter会自动release旧值,retain新值: *:assign:(适用于非oc对象)  这个是默认的值 *:copy:release旧值,copy新值: @property (retain) NSString *name; // 同类型的参数不能同时写 // @property

黑马程序员-oc对象的内存管理

oc没有java的垃圾回收机制,所以对象的内存释放很重要,基本数据类型,我们不用理会,编译器会处理: oc的每个对象内部都由一个计数器,用来记录当前有几个指针在指向该对象:当计数器为0时该对象会从内存中释放: 相关方法和概念: 1:retain:对象方法,调用该对象方法,计数器+1,有返回值,返回对象本身: 2:release:没有返回值,计数器-1: 3:retainCount:获取当前计数器的值: 4:dealloc:当对象被回收时,就会调用该方法,覆盖该方法时一定要调用[super dea