黑马程序员_OC学习之内存管理

------- IOS培训android培训、期待与您交流! ----------
也许学习例如C#等高级语言我们不需要,关心内存管理,因为他有自动回收的功能。
但是OC中却是继承了C语言的内存管理的方式--手动管理
移动设备的内存极其有限,每个app所能占用的内存是有限制的
当app所占用的内存较多时,系统会发出内存警告,这时得回收一些不需要再使用的内存空间。比如回收一些不需要使用的对象、变量等
1、 Objective-c的对象生成之后,需要一个指针来指向它。
ClassA *class1 = [[ClassA alloc] init];
2、objective-c的对象在使用完成之后不会自动销毁,需要执行dealloc来释放空间(销毁),否则内存泄露。
[class1 dealloc];
这带来一个问题,下面代码中class2是否需要调用dealloc?
ClassA *class1 = [[ClassA alloc] init];
ClassA *class2 = class1;
[class1 hello];//输出hello
[class1 dealloc];
[class2 hello];//能够执行这一行和下一行吗?
[class2 dealloc];
不能,因为class1和class2 只是指针,它们指向同一个对象,[class1 dealloc]已经销毁这个对象了,不能再调用[class2 hello]和[class2 dealloc]. class2 实际上是个无效指针。
3、Objective-c采用了引用计数(ref count或者retain count).对象的内部保存一个数字,表示被引用的次数。例如,某个对象被两个指针所指向(引用)那么它的retain count为2.需要销毁对象的时候,不直接调用dealloc,而是调用release.release会让retain count减一,只有 retain count等于0,系统才会调用dealloc真正销毁这个对象。
ClassA *class1 = [[ClassA alloc] init];//对象生成时,retain count = 1;
[class1 release];//release使retain count减1,retain count = 0,dealloc自动被调用,对象被销毁
我们回头看看刚刚那个无效指针的问题,把dealloc改成release解决了吗?
ClassA *class1 = [[ClassA alloc] init];//retain count = 1
ClassA *class2 = class1;//retain count = 1
[class1 hello];//输入hello
[class1 release];//retain count = 0,对象被销毁
[class2 hello];
[class2 release];
[class1 release]之后,class2依然是个无效指针。问题依然没有解决。


4、 Objective-c指针赋值时,retain count 不会自动增加, 需要手动 retain.
ClassA *class1 = [[ClassA alloc] init];//retain count = 1;
ClassA *class2 = class1;//retain count = 1;
[class2 retain];//retain count = 2
[class1 hello];// 输出hello
[class1 release];//retain count = 2 - 1 = 1
[class2 hello];输出hello
[class2 release];retain count = 0,对象被销毁
问题解决!注意,如果没有调用[class2 release],这个对象的retain count 始终为1,不会被销毁,内存泄露。
这样的确不会内存泄露,但似乎有点麻烦,有没有简单点的方法?
 
5.内存管理原则
   5.1. 原则分析 
  只要还有人在用某个对象,那么这个对象就不会被回收
  只要你想用这个对象,就让对象的计数器+1
  当你不再使用这个对象时,就让对象的计数器-1
 


  5 .2. 谁创建,谁release
   如果你通过alloc、new或[mutable]copy来创建一个对象,那么你必须调用release或autorelease
  换句话说,不是你创建的,就不用你去[auto]release


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


6   autorelease pool原理剖析。
6.1  autorelease pool不是天生的,需要手动创立。只不过在新建一个iphone 项目时,xcode会自动帮你写好。autorelease pool的真名是NSAutoreleasePool.
6.2   NSAutoreleasePool 内部包含一个数组( NSMutableArray), 用来保存声明为autorelease的所有对象。如果一个对象声明为autorelease,系统所做的工作就是把这个对象加入到这个数组中去。
     ClassA *class1 = [[[ClassA alloc] init] autorelease];//retain count = 1,把此对象加入autorelease pool中
6.3 NSAutoreleasePool 自身在销毁的时候,会遍历一遍这个数组,release  数组中的每个成员。如果此时数组中成员的retain count为1,那么release之后,retain count为0,对象正式被销毁。如果此时数组中成员的 retain count  大于1,那么 release之后,retain count大于0,此对象依然没有被销毁,内存泄露。
6.4 默认只有一个autorelease pool
 

代码案例:

int main()

{

    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

    

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

    

    [pool release]; // [pool drain];

    

    @autoreleasepool

    {

    

        // 1

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

        

        // 0

        // [p release];

    }

    

    return 0;

}



void test()

{

    @autoreleasepool

    {// {开始代表创建了释放池

        

        // autorelease方法会返回对象本身

        //调用完autorelease方法后,对象的计数器不变

        // autorelease会将对象放到一个自动释放池中

       // 当自动释放池被销毁时,会对池子里面的所有对象做一次release操作

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

        

        p.age = 10;

        

        @autoreleasepool

        {

            // 1

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

            p2.age = 10;

            

       }

        

        Person *p3 = [[[Personalloc]init]autorelease];

        

    }// } 结束代表销毁释放池

}

 

 

 

 

 

 ------- IOS培训android培训、期待与您交流! ----------

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值