第三讲:Obj-C 内存管理1 - 黄金法则

news/2024/7/20 14:27:10 标签: 内存管理, c/c++

转:http://tigercat1977.blog.163.com/blog/static/2141561122012111293337435/

第三讲:Obj-C 内存管理1 - 黄金法则 

 
主要内容
      OC内存管理原理
      OC内存管理相对 C/C++ 有何好处
      OC内存管理的 alloc, retain, release
      遛狗原则
      OC 对象生命周期

内存管理  黄金法则
      The basic rule to apply is Everything that increases the refernce counter with alloc,
[mutable] copy [Whith Zone:] or retain is charge of the corresponding [auto] release.

      如果对一个对象使用了  alloc, [mutable] copy, retain, 
那么你必须使用相应的 release 或者 autorelease


内存管理类型定义

     基本类型   任何 C 的类型,如:
     int,  short,  char,  long,  long long,  struct,  enum,  union 等属于基本类型或者结构体
     内存管理对于 C 语言基本类型无效

     OC类型 (非基本类型)
     任何继承于 NSObject 类的对象都属于 OC 类型
     也就是除了 C 之外的其他类型

OC 对象结构
第三讲:Obj-C <a class=内存管理1 - 黄金法则 - tigercat1977 - tiger notes" src="http://img9.ph.126.net/U5zoH737mB8ivqLU7oj40w==/6597235792913799179.jpg" width="479" height="254" />

C / C++ 内存管理原理
第三讲:Obj-C <a class=内存管理1 - 黄金法则 - tigercat1977 - tiger notes" src="http://img8.ph.126.net/I6g427t-7FZM4IE0ep-aWg==/6597992256912416598.jpg" width="476" height="225" />

C / C++ 内存管理代码
      Int *p1 = malloc(100);
      Int *p2 = p1;
      Int *p3 = p1;
      Free(p2);

      Free(p2);

内存管理对象
      对于OC的对象,非基本对象(int,  short, struct)
      NSObject, 凡是继承于 NSObject
      每一个对象都有一个 retainCount 计数器。表示当前的被应用的计数器。如果计数为0,那么就真正的释放这个对象

内存管理图示
      这就是引用计数的理论。在实际应用中,通过只有两个原因我们才会创建一个对象:
          1. 作为一个实例变量保留。
          2. 在函数内部作为临时变量使用。
      大多数情况下,一个实例变量的设置器(setter)会自动释放(autorelease)
      原来引用的对象,同时保留(retain)新的。你只需要保证在 dealloc 函数中释放(release)了它就行了。
第三讲:Obj-C <a class=内存管理1 - 黄金法则 - tigercat1977 - tiger notes" src="http://img0.ph.126.net/7wgDw3qbHMTEabom3-bdBw==/6597958172051956680.jpg" width="563" height="155" />

遛狗原理
第三讲:Obj-C <a class=内存管理1 - 黄金法则 - tigercat1977 - tiger notes" src="http://img8.ph.126.net/rzKrA9nGturFSBehvQ8VqA==/6597233593890536288.jpg" width="548" height="281" />

OC内存管理
第三讲:Obj-C <a class=内存管理1 - 黄金法则 - tigercat1977 - tiger notes" src="http://img7.ph.126.net/ZbgzV9jFvJjD81aOFPTIpw==/6598267134819188007.jpg" width="546" height="276" />

alloc retain release 函数
      alloc 函数是创建对象使用,创建完成后计数器为 1
      只用一次

      retain 是对一个对象的计数器 +1
      可以调用多次

      release 是对一个对象计数器 -1
      减到 0 对象就会从内存中释放

OC内存管理
      Objective - C 类中实现了引用计数器,对象知道当前被引用了次数。
      最初对象的计数器是 1 。
      如果需要引用对象了,可以给对象发送  release 消息,这样对象计数器就加 1。
      当不需要引用对象了,可以给对象发送  release 消息,这样对象计数器就减 1。
      当计数器减到 0,自动调用对象的 dealloc 函数,对象就会释放内存。
      计数器为 0 的对象不能再使用 release 和其他方法 。

retain / release 例子
      NSMutableString *str = [[NSMutableString alloc] init];
                                      // str 计数器为 1
      [str retain];                // str 计数器为 2
      [str retain];                // str 计数器为 3
      [str release];              // str 计数器为 2
      [str release];              // str 计数器为 1
      [str release];              // str 计数器为 0,   对象释放内存
   
内存管理总结
Objective - C 的内存管理机制与 .Net / Jave 那种全自动的垃圾回收机制是不同的,它本质上还是 C 语言中的手动管理方式,只不过稍微加了一些自动方式。
      Objective - C 的内存管理是基于引用计数的。要做的事情只是关注的引用,而释放内存的工作实际上由运行环境完成。
      在最简单的情形中,分配的(alloc)对象,或者是保留(retain)在一些地方的对象,都需要发送一个 release 消息。这也意味着,如果使用了一次 alloc,然后又 retain 了一次,那你需要 release 两次才能释放对象的内存。

下面三种增加对象技术器
      1. 当明确的使用 alloc 方法来分配对象。
      2. 当明确的使用 copy [WithZone:] 或者 murableCopy[WithZone:] 来 copy 对象时。
      3. 当明确使用 retain 消息。

      上述三种方法使得计数器增加,那么就需要使用 [auto] release 来明确释放对象,也就是递减计数器。

遛狗原则举例 (一只狗时)这方法不够完善

   

// Dog.h #import <Foundation/Foundation.h> @interface Dog : NSObject { int _ID; } @property int ID; @end


   

// Dog.m #import "Dog.h" @implementation Dog @synthesize ID = _ID; - (void) dealloc { NSLog(@"dog %d is dealloc", _ID); [super dealloc]; } @end



   

// Person.h #import <Foundation/Foundation.h> #import "Dog.h" @interface Person : NSObject { Dog *_dog; } - (void) setDog:(Dog *)aDog; - (Dog *) dog; @end


   

// Persen.m

@implementation Person - (void) setDog:(Dog *)aDog { if (aDog != _dog) { // _dog = aDog; // [_dog retain]; _dog = [aDog retain]; // 让计数器 +1 } } - (Dog *) dog { return _dog; } - (void) dealloc { NSLog(@"person is delloc"); // 把人拥有的 _dog 释放 [_dog release]; [super dealloc]; } @end



   

// main.m #import <Foundation/Foundation.h> #import "Dog.h" #import "Person.h" int main (int argc, const char * argv[]) { @autoreleasepool { NSLog(@"Hello, World!"); Dog *dog1 = [[Dog alloc] init]; [dog1 setID:1]; Person *xiaoLi = [[Person alloc] init]; // 小丽要遛狗 [xiaoLi setDog:dog1]; Person *xiaoWang = [[Person alloc] init]; [xiaoWang setDog:dog1]; NSLog(@"dog1 retain count1 is %ld", [dog1 retainCount]); // 输出:dog1 retain count1 is 3 [dog1 release]; NSLog(@"dog1 retain count2 is %ld", [dog1 retainCount]); // 输出:dog1 retain count2 is 2 [xiaoWang release]; NSLog(@"dog1 retain count3 is %ld", [dog1 retainCount]); // 输出:person is delloc // :dog1 retain3 count is 1 [xiaoLi release]; // 输出:person is delloc // :dog 1 is dealloc } return 0; }


遛狗原则举例2 (两只狗时)这方法比较完善

   

// Dog.h #import <Foundation/Foundation.h> @interface Dog : NSObject { int _ID; } @property int ID; @end


   

// Dog.m #import "Dog.h" @implementation Dog @synthesize ID = _ID; - (void) dealloc { NSLog(@"dog %d is dealloc", _ID); [super dealloc]; } @end



   

// Person.h #import <Foundation/Foundation.h> #import "Dog.h" @interface Person : NSObject { Dog *_dog; } - (void) setDog:(Dog *)aDog; - (Dog *) dog; @end


   

// Persen.m

@implementation Person - (void) setDog:(Dog *)aDog { if (aDog != _dog) {

[_dog release]; // 要注意的地方,提前 release _dog = [aDog retain]; // 让计数器 +1 } } - (Dog *) dog { return _dog; } - (void) dealloc { NSLog(@"person is delloc"); // 把人拥有的 _dog 释放 [_dog release]; [super dealloc]; } @end



   

// main.m #import <Foundation/Foundation.h> #import "Dog.h" #import "Person.h" int main (int argc, const char * argv[]) { @autoreleasepool { Dog *dog1 = [[Dog alloc] init]; [dog1 setID:1]; Dog *dog2 = [[Dog alloc] init]; [dog2 setID:2]; Person *xiaoLi = [[Person alloc] init]; // 小丽要遛狗 [xiaoLi setDog:dog1]; [xiaoLi setDog:dog2]; NSLog(@"dog1 retain count is %ld", [dog1 retainCount]); //输出:dog1 retain count is 1 [dog1 release]; //输出:dog 1 is dealloc NSLog(@"dog2 retain count is %ld", [dog2 retainCount]); //输出:dog2 retain count is 2 [xiaoLi release]; //输出:person is delloc NSLog(@"dog2 retain count is %ld", [dog2 retainCount]); //输出:dog2 retain count is 1 [dog2 release]; //输出:dog 2 is dealloc } return 0; }

 

转载于:https://www.cnblogs.com/jackljf/archive/2013/03/07/3589253.html


http://www.niftyadmin.cn/n/1795312.html

相关文章

【protobuf进阶】读取proto实体里的extensionObject对象的方法

//设置扩展对象 ProtoBuf.Extensible.AppendValue //读取扩展对象 ProtoBuf.Extensible.GetValue 最近通过C#的TcpClient调用java服务器接口&#xff0c;使用了protobuf的协议&#xff0c;在调试接口的时候一直取不到extensionObject Response.cs如下 //----------------------…

1 - 部署第一台域控制器

环境信息CONTOSO集团是一家跨国企业&#xff0c;总部坐落于美国的雷德蒙德&#xff0c;并且在日本和中国设有分公司&#xff0c;日本分公司位于东京&#xff0c;而中国分公司在北京、上海和苏州均有办事处。随着企业规模的扩大&#xff0c;CONTOSO集团决定使用AD域服务对现有IT…

总结一致性哈希(Consistent Hashing)[转]

在大型web应用中&#xff0c;缓存可算是当今的一个标准开发配置了。在大规模的缓存应用中&#xff0c;应运而生了分布式缓存系统。分布式缓存系统的基本原理&#xff0c;大家也有所耳闻。key-value如何均匀的分散到集群中&#xff1f;说到此&#xff0c;最常规的方式莫过于hash…

一、Spring——IoC

IOC概述Spring中IOC的概念&#xff0c;控制反转概念其实包含两个层面的意思&#xff0c;“控制”是接口实现类的选择控制权&#xff1b;而“反转”是指这种选择控制权从调用者转移到外部第三方或容器的手中。BeanFactory、ApplicationContext和WebApplicationContext是Spring框…

大话存储系列7——文件系统和IO处理流程

1、文件系统 在早期的计算机系统中&#xff0c;每个程序都必须自己管理磁盘&#xff0c;在磁盘中放自己的数据&#xff0c;程序需要直接和磁盘控制器打交道。有多少个程序要利用磁盘&#xff0c;就有多少个磁盘交互启动接口。 在没有文件系统的计算机上&#xff0c;如果一个程序…

验证码识别软件的下载

打码简单来说就是打验证码&#xff0c;输入验证码的意思。因为大家在注册网站时都必需要手工输一段验证码&#xff0c;而这段验证码是随机生成的&#xff0c;目的就是为了让一些居心不良人的恶意注册网站&#xff0c;而防止其散布垃圾广告或 是骗人广告的目的。因为这些人想快速…

python通过百度云api的方式上传或下载文件

1、参考网址&#xff1a;GitHub - ly0/baidupcsapi: 百度网盘api 树莓派实现上传文件到百度云_Camlin_Z的博客-CSDN博客 2、编写一个脚本实现长传图片&#xff0c;命名为&#xff1a;pic_upload.py import progressbar from baidupcsapi import PCS class ProgressBar(): …

vc实现多语言资源

MS Windows操作系统是一个世界上广泛使用的操作系统&#xff0c;对于不同语种的国家MS Windows有相应语种的版本。在不同语种的Windows平台上应该运行相应语种的应用程序。也就是说程序的用户界面&#xff08;如菜单、对话框、状态条&#xff09;中的提示文字应该使用和Windows…