zoukankan      html  css  js  c++  java
  • Object C学习笔记4-内存管理

    Object C学习笔记4-内存管理

    2014-01-24 16:56 by 贺臣, 605 阅读, 1 评论, 收藏, 编辑

      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的实例,让占用的资源立马释放掉。

    转载于:http://www.cnblogs.com/qingyuan/p/3532563.html

  • 相关阅读:
    [转]《三国演义》人名英文翻译妙评 你也来评评!
    Effective C++:改善程序技术与设计思维的55个有效做法(第三版)(中文版)(预订)Effective C++ 3RD
    A Closer Look At Parallax Occlusion Mapping
    [转]收录全部作品,《寂静岭套装》发售开始
    [转]程序员版《桃花庵》
    Cg 1.5 Beta 2
    FilteredTextBox控件
    CollapsiblePanel控件
    DynamicPopulate控件
    HoverMenu控件的使用
  • 原文地址:https://www.cnblogs.com/wodehao0808/p/3592090.html
Copyright © 2011-2022 走看看