iOS-内存管理就这么简单1

本文深入探讨了Objective-C中的内存管理机制,通过对比C语言,详细解析了变量生命周期、堆栈内存分配及其管理方式,并利用生动的例子介绍了引用计数的概念。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

文明看博转载是对自己的尊重也是对学者的鼓励,欢迎讨论

-------------iOS-图说OC内存管理----------------

一.OC源代码分解及到C语言的讨论

在此我们来看一下语言的结构,把源代码的编写形式分解。把内存的组织分解,然后把源代码的编写映射到内存中的运行时,只要掌握源代码的内存映射各个要素之间的对应关系,就能很好的掌握内存管理,思想很重要一切都为乐coding服务。
一个条C语言的语句:

int number;
1.上面的语句声明了一个int 类型的变量,这时候number的值是不确定的,number被编译器编译之后,number就是一个虚拟内存地址(可以想象,计算机资源这么宝贵,不可能去花空间来储存变量名的字符串,在源代码层面变量名是给人看的,在编译器的眼中任何的变量名,函数名,常量等都是虚拟地址)。


int number=8;
2.这就相当于把8的值放到number的虚拟内存中去。number是值类型,如果它是在函数中的话,当函数执行完成后,它的生命周期就结束了会被释放,它的生命周期由它的作用域决定。


typedef struct TestStruct{
    int number;
}TestStrutType;


TestStrutType number;
    number.number =8;
<p class="p1"><span class="s1">NSLog</span><span class="s2">(</span><span class="s3">@"number=%d number.number=%d"</span><span class="s2">,&number,&number.</span><span class="s4">number</span><span class="s2">);</span></p>


运行结果:

2015-01-17 15:33:33.575 MemoryManager[816:32368] number=1587763888 number.number=1587763888



3.声明一个结构体,用它来声明一个number变量,并设置number变量中的number成员的值为 8;被编译之后其实结构体变量number和其成员变量都在同一个虚拟内存中,它们也是值类型,生命周期由它的作用域决定,说白了就是函数调用返回决定。说到这里就得到一个结论,变量编译之后是一个虚拟内存地址,而变量的类型决定了去怎样读取它的值。



    TestStrutType *number= malloc(sizeof(TestStrutType));
    number->number =8;

4.声明一个TestStructType类型的指针变量number,并通过malloc手动分配对应类型大小的堆内存块,并把堆内存块的指针存放到栈上变量number指针变量的虚拟内存上,通过指针变量number给成员变量number赋值,这时候的数字8是存放在堆内存块中的。当number指针变量所在的函数返回,也就是number的生命周期结束了,通过malloc分配的内存块还在,它并没有被释放,这样就会造成内存泄漏。栈上的内存变量会自动释放,堆上的内存块是手动分配的就要手动释放,由于栈内存变量和堆内存块的管理机制不相同,这就引出了内存管理问题。


NSObject *obj = [[NSObject alloc]init];

5.声明一个NSObject类型的指针变量变量obj,指向一个NSObject类型的堆内存块。[[NSObject alloc]init]本质上就是调用malloc函数分配一个NSObject类型大小的内存块,并把它的堆内存虚拟地址赋值给栈上的指针变量obj,当obj所在的函数返回,也就是obj的生命周期结束了,这时obj被释放了,但是[[NSObject alloc]init]分配的堆内存块还在,这时就会出现内存泄漏的问题。由于堆内存的对象时手动释放,什么时候释放,什么时候不该释放,就成了编程中要考虑的问题,如果提前释放,当访问对象时就会报错,如果该释放的时候没有被释放,就会造成内存浪费。Object-C语言采用的是引用计数的方式来达到内存管理的。上面都只是问题的铺垫,下面我们将要了详细的对引用计数的内存管理全面的讲解。


在OC语言中最常用的语法格式是 (类型)*(指针变量) = ([[(类型)alloc]init])的形式来声明变量的。下面我分把它分解来说明。首先从等号分开。等号左边的是指针变量,等号右边的是该类型的实例内存块。等号左边的是在栈上的虚拟内存上,等号右边的是堆上的内存上。等号左边的变量是自动管理的,等号右边的内存块是要编程人要手动的管理的。下面我们就把OC的常用的表达式模拟成一个场景:打一个比方(等号的左边指针变量相当于一个人)(等号相当于把一根线交给人)(等号的右边相当于飘在空中的气球)(retain函数相当于retainCount加1)(release函数相当于retainCount 减1)(retainCount表示该气球是不是要被销毁掉,为0销毁,大于0保留),(autoReleasePool的变量相当于一个管理者)。于是通过上面的组合就得到下面的一些情景。

1.

NSObject *obj;   //表示有一个人出现了,但是这个人并没有拉着气球


2.

[[NSObject alloc]init];   //出现了一个气球,并没有任何人拉着它,但是它的retainCount为1所以它不能背销毁,(内存泄漏)


3.

NSObject *obj = [[NSObject alloc]init]; //obj这个人通过线拉着一个气球





4.

[[[NSObject alloc]init] retain];   //出现了一个没有线的气球,但是它的retainCount为2所以它不能背销毁,(内存泄漏)



5.

[[[NSObject alloc]init] release];   //刚创建就要被销毁的气球




6.
NSObject *obj = [[NSObject alloc]init]; //obj这个人通过线拉着一个气球
    [obj autorelease];                      //obj这个人把气球的线交给了管理人员,retainCount不变,




7.

NSObject *obj = [[NSObject alloc]init]; //obj这个人通过线拉着一个气球
    NSObject *obj2 = obj;                   //obj2这个人和obj这个人共用一根线共同的拉着个气球,retainCount不变






8.

NSObject *obj = [[NSObject alloc]init]; //obj这个人通过线拉着一个气球
    NSObject *obj2 = [obj retain];          //obj2这个人和obj这个人用不同的线拉着同一个球,retainCount为2不变





9.

NSObject *obj = [[NSObject alloc]init]; //obj这个人通过线拉着一个气球
    [obj release];                          //obj把线减掉 retainCount减1,如果retainCount为0将会被销毁


待续。。。。。。。。。。。。。





评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值