objective-c 内存管理小结

来源:互联网 发布:手机怎么打开php视频 编辑:程序博客网 时间:2024/05/22 10:24

内存管理的黄金法则:  如果对一个对象使用了alloc, copy, retain 方法,那么必须使用相应的release 或 autorelease 释放



内存管理的概念:

          内存管理是关于如何管理对象生命周期的编程原则.(主要是针对OC的对象,所有的对象都继承NSObject)



  • 引用计数(retainCount)

     引用计数是cocoa 中提供一个机制来表示对象被引用的次数,称为"引用计数"(refernce counting) 或 "保留计数"(retain counting) .引用计数的值表示对象有几个"人"在使用它.

     

     当对一个对象使用 alloc, retain, copy 方法,对象的引用计数 +1 .

     当对一个对象使用 release 或者 autorelease 方法,对象的引用计

数 -1.

     当对象的引用计数为 0 时, 系统会自动调用 dealloc 方法销毁对象

          -(void)dealloc

          {

               [super dealloc];

          }

  • 对象所有权

     所有者是如何获得某对象的所有权的?

          当一个所有者做了以下某个动作时,它就拥有了一个对象的所有权(ownership).

          alloc, allocWithZone:,copy, copywithZone:, mutableCopy

mutableCopyWithZone:, retain

     

     如果你拥有了某个对象的所有权,在不需要某一个对象时,需要释放他们(release, autorelease)


     如何持有对象:

          example:

               -(void)setA:(A *)a

               {

                    if(_a != a)

                    {

                         [_a release];

                         _a = [a retain];

                    }

               }

               释放旧对象,保持新对象

               当保留某对象时,需在dealloc方法中释放该对象

               exp:

                    -(void)dealloc

                    {

                         [_a release];          //释放保留的对象

                         [super dealloc];

                    }

               

  • 合成存取器

     @property (argu1, argu2, argu3) NSString *name;

          argu1:  automic 多线程环境下,存在线程保护(默认)

                      nonautomic  多线程环境下, 不存在线程保护

          

          argu2:  assign 直接复制 (默认)

                         -(void)setName:(NSString *)name{

                              _name = name;

                         }

                         

                      retain  保留对象

                         -(void)setName:(NSString *)name{

                              if(_name != name)

                              {

                                   [_name release];

                                   _name = [name retain]; 

                              }

                         }

                         

                      copy   复制对象

                         -(void)setName:(NSString *)name{

                              if(_name != name)

                              {

                                   [_name release];

                                   _name = [name copy]; 

                              }

                         }

                         

          argu3:  readwrite 生成 setter ,getter方法 (默认)

                      readonly 只生成  getter 方法


      在dealloc 方法中,将[object release] 改写成 self.object = nil.

  • 自动释放池( NSAutoreleasePool )

          自动释放池的概念及作用:

               自动释放池是OC的一种内存自动管理机制

               当自动释放池销毁时,会对池中的每一个对象调用一次release方法.


          自动释放池的原理:

               自动释放池就像一个数组, 以栈的数据结构压入每个对象,采用 " 先进后出 " 的原则

          自动释放池嵌套

               autorelease会将对象添加到离他最近的自动释放池( 注意: 逻辑最近 )

               exp:

                    NSAutoreleasePool *pool1 = [[NSAutoreleasepool alloc] init];

                    Person *person = [[Person alloc] init];

                    [person autorelease];     //添加到pool1中

                    

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

                    Dog *dog = [Dog alloc] init];

                    [dog autorelease];          //添加到pool2中

               

                    // 这里注意嵌套原则 ,pool2嵌套在pool1中,所有应该先释放pool2

                    [pool2 release];

                    [pool1 release];


          处理大量数据的例子

               exp:

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

                    for(int i = 0; i < 1000000; i++)

                    {

                         if(i % 1000 == 0)

                         {

                              [pool release];

                              pool = [[NSAutoreleasePool alloc] init];

                         }

                         NSArray *array = [[NSArray alloc] init];

                         [array autorelease];

                    }

                    [pool release];



  • 循环引用

          当对象A retain 对象B,同时 对象B retain 对象A.这时两个对象A 和 B都没办法得到释放.这种情况我们称之为循环引用. 因此,使用代理设计模式,我们通常使用assign 使其中的一个运用直接赋值.

  • 数组的内存管理

          当数组添加一个元素( 对象 )时,会对该元素进行 retain ,对象引用计数 +1

          当数组删除一个元素( 对象 )时,会对该元素发送一次release消息, 对象引用计数 -1.

          当数组删除所有元素( 对象 )时,会对数组中每一个元素发送一次release消息,对象引用计数 -1.

          当数组release 时,会对数组中的每一个元素( 对象 )发送一次release消息, 对象引用计数 -1.


  • 内存中的区域划分

          栈区(stack): 由系统自动分配和释放, 存放 方法的参数值,局部变量的值等. 采用 " 先进后出 " 的原则. 特点: 有序,速度快,容量小

          堆区: 一般由程序员分配和释放,如果不释放,则出现内存泄露. 程序退出时,系统会收回你的内存. 特点: 无序, 速度慢, 容量大.

          静态存储区: 全局变量( 外部变量 )和静态变量都存放在静态区域. (注意: 未初始化的全局变量 和 静态变量存放在一起, 已初始化的存放在一起.) 当程序退出时,系统回收.

          常量区: 存放常量的内存区域,当程序退出时,系统回收 (注意: 当 const 在修饰的 局部 常量数据类型时, 该数据存放在栈区 ,生命周期与该区域有关)

          代码区: 存放二进制代码的区域


  • ARC

          ARC自动引用技术(automatic reference counting), 当你在编译程序时提供自动管理内存功能, 它会为代码自动加入内存的控制代码,控制对象的生命周期.如此一来,大大简化了内存管理的步骤.(注意: 版本支持是在IOS4(不支持弱引用) , IOS5上).

  • 新语法的内存管理

          如下程序:

                NSArray *array = @[@12, @34, @56, @78];

               创建数组对象时,由XCODE自动为我们调用了autorelease 方法,不需要我们去手动释放.


                NSMutableArray = *mutableArray = [@[@12, @34, @56, @78] mutableCopy];

               代码可拆分为: 

               NSArray *array = @[@12, @34, @56, @78];

               NSMutableArray = *mutableArray =[array mutableCopy]

               由于对象调用了mutableCopy方法,所有需要我们手动调用一次release 方法来释放该对象,同时系统会为mutableArray 调用一次autorelease 方法                      



原创粉丝点击