1、 
 内存管理方式
 
     
垃圾回收机制:(Garbage
Collection),有系统管理内存,开发人员需要管理
   
    注:OC从2.0之后就开始支持垃圾回收机制,但是只适用于OS开发,(苹果电脑的操作系统),我们iOS平台是不支持垃圾回收机制;(面试题)

不支持垃圾回收机制,OC是如何管理内存的呢?

       
//内存不释放
就叫内存泄露
//OC通过引入计数器管理内存



图中那个的行为
 
  OC中操作
OC中方法
根据照明设备所做的动作
对对象的操作

开灯
 
生成对象
alloc/copy/new
需要照明
持有对象
return
不需要照明
释放对象
release/autorelese(不会立即释放且与@autoreleasepool配合使用)
关灯
废弃对象
 
dealloc

       
//图中需要照明的人数,就代表引用计数

//1.当第一人"需要照明",引用计数+1
   
有0-->1

       
//2.当第二个人"需要照明",引用计数+1
   
有1-->2

       
//3.当第二个人"需要照明",引用计数+1
   
有2-->3

       
//4.当有一个人"不需要照明",引用计数-1
   
有3-->2

       
//5.当再有一个人"不需要照明",引用计数-1
   
有2-->1

       
//6.当再有一个人"不需要照明",引用计数-1
   
有1-->0
2、iOS平台下适用计数器如何管理内存,有两种方式
 
   1.MRC:(Manual Reference
Counting),手动引入计数器,有开发人员通过手动引入计数器来管理内存。
 
    2.ARC:(Automatic Reference
Counting),自动引入计数器,由系统通过引入计数器管理内存
       
//学习好MRC是为了更好使用ARC,iOS5.0之后就有了ARC;
ARC和MRC的混编
   
    1.如果工程环境是ARC,而部分文件使用了MRC,使用一个参数   
-fno-objc-arc
   
    2.如果工程环境是MRC,而部分文件使用了ARC,使用一个参数
    -fobjc-arc
==============================================================
例子: 1.自己创建的对象自己持有;
Person.h
@interface
Person
: NSObject
//名字的属性
@property
(nonatomic,copy)NSString
*name;
@end

Person.m
@implementation
Person
//dealloc
方法是对象被销毁的时候自动调用的方法,不需要手动调用,由于dealloc方法是重写的父类,所以重写此方法的时候,一定要把父类的方法内容也写上
-
(void)dealloc 
 {
  NSLog(@"Person%@对象被销毁了",_name);

//以后重写dealloc方法时一定调用[super
dealloc];  且此方法一定要写在最下面

   
[super
dealloc];
}
@end

main.m
Person
*p
= [[Person
alloc]init];//alloc会造成对象的引用计数器由0-->1
       
p.name
=
@"缓缓";
       
//如何判断一个对象是否被持有,就看它的引用计数

//retainCount
:对象的引用计数

       
NSLog(@"%lu",p.retainCount);
//计数器为1
       
//如果自己创建的对象不使用时,释放对象,使用release

[p release];

//
   
NSLog(@"%lu",p.retainCount);
     
对象死了就不能再使用它了

//
    [p
release];   
不要过度释放,也等于操作僵尸对象
 Person
*p2 =
[[Person
alloc]init];
  //0--->1
       
p2.name
=
@"武媚娘";
3、retain可以让对象的引用计数
+1

       
//非自己创建的对象,自己也能持有

p2 =  [p2 retain];
//由1--->2

NSLog(@"%lu",p2.retainCount);

//非自己创建的对象,自己也能持有

Person
*p3 =
[p2 retain];

NSLog(@"%lu",p3.retainCount); 
//2--->3

[p2 release];//3-->2

[p2 release];//2-->1

[p3 release];//1-->0

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

p4.name
=
@"小骨";

[p4 retain];//2

[p4 retain];//3

[p4 retain];//4

[p4 release];//3

[p4 release];//2

[p4 release];//1

       
[p4 release];//0
//
     [p4
retain];//人死不能复生,对象死也不能复生
4、 方法的基本使用
 
      1.retain :
计算器 +1   ,会返回对象本身;(返回值为id泛类型)
 
     
2.release : 计数器 -
1,没有返回值
 
     
3.retainCount
的作用:获取当前对象的计数器数值
 
   
  4.dealloc
当一个对象被销毁的时候,系统会自动调用,再次方法中一定要调用[super
delloc];且这句话要放到最后;
5、 概念
 
  //僵尸对象:所占内存被回收的对象,就叫僵尸对象,僵尸对象不能再使用
       
//野指针:指僵尸对象的指针就叫野指针
       
//空指针:没有志向任何东西的指针就叫空指针叫空指针,(nil,NULL,0),给空指针发送消息

//
  alloc 对应 
dealloc

       
// 
retain  对应 release
   
    区别: [[Person
alloc]init];   内存永远不会被释放
       
//       
[[[Person alloc]init]release]; 
创建的同时立即就被释放掉
       
//autorelease 相比
release,也能造成引用计数器-1,不过autorelease
不是立即-1,会在未来某段时间做-1操作;
6、 autorelease 执行实质,对一个对象使用autorelease
操作,这个对象的引用计数器不会立即减1,如果把这个autorelease 
操作放到自动释放出中,会在出池子的一瞬间减1,如果你没有放到池子中,不会对autorelease 
操作对象进行减1;
 注意:你要使用autorelease
必须和自动释放池配合使用
//       
Person *p5 = [[Person alloc]init];//0--->1
//
     
 p5.name =
@"杀阡陌";
//       
[p5 autorelease];//1
//       
NSLog(@"%lu",p5.retainCount);
=======================================================
7、创建自动释放池的两种形式

//第一种形式

//
 
 NSAutoreleasePool 
自动释放池类
NSAutoreleasePool
*pool =
[[NSAutoreleasePool
alloc]init];

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

p6.name
=
@"白子画";

[p6 autorelease];//或者用[p6
release];

       
NSLog(@"%lu",p6.retainCount);

[pool release];

//第二种形式

@autoreleasepool
{

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

p7.name
=
@"糖宝";

[p7 autorelease];//未来的时间减1,出自动释放池减1

//           
[p7 release];//-1
   
//过度释放

           
NSLog(@"%lu",p7.retainCount);

   
}//此时也会引起过度释放,是由autorelease引起的
8、 内存管理的原则

//水污染谁治理,谁alloc谁release,谁return谁release,autorelease

//你想占用某个对象,就应该让对象的计数+1,(也就是让对象做以retain操作)

       
//当你不想持有(占有)某个对象时,就应该让对象的引用计数-1,(也就是让对象做一release操作)
重复使用的释放可以设置带有参数的宏定义,减少繁琐的程序
#define kRelease_Safe(_point) [_point release];_point =
nil;
       
Person
*p8 =
[[Person
alloc]init];
       
p8.name
=
@"紫熏";
       
Person
*p9 =
[p8 retain];
 
     
kRelease_Safe(p8);
       
NSLog(@"%@",p9.name);
 
      kRelease_Safe(p9); 
//       
[p8 release];//对一个空指针发送消息,没有任何影响
9、 NSMutableArray
*mArray =
[[NSMutableArray
alloc]initWithCapacity:0];

//向数组中添加十个人

for
(int
i
= 0;
i < 10
;
i ++) {

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

person.name
=
[NSString 
stringWithFormat:@"%d",i];

//数组在添加元素的时候,会对添加的元素做一次retain操作

[mArray addObject:person];

kRelease_Safe(person);

       
}
       
NSLog(@"%@",mArray);

//数组在释放自己之前,会对之前添加到数组中的元素进行引用计数减1的操作

       
kRelease_Safe(mArray);
       
//此时我们没有alloc
也没有retain ,所以不需要对数组mArray2 的内存释放负责

       
NSMutableArray
*mArray2 =
[NSMutableArray
array];//

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

p10.name
=
@"朱然";

[mArray2 addObject:p10];

       
kRelease_Safe(p10);
       
NSString
*string =
[[NSString
alloc]initWithString:@"12345678912345"];
       
NSLog(@"%ld",string.retainCount);
 总结:非重点,但是考试一般会问及: 当使用stringWithFormat:创建的字符串对象当长度小于10的时候,在常量区;大于等于10的时候,在堆区;

//使用其他方法创建的字符串都在常量区

NSString
*string2 =
[NSString
stringWithFormat:@"1234567890"];

       
NSLog(@"%lu",string2.retainCount);
       
//没人去释放字符串,stringWithFormat: 
计数器1,其他计数为-1;
======================================================
10、 copy
对象能够使用copy操作的前提是,此类必须遵循NSCopying 协议
       
//浅拷贝,只拷贝地址,同时对象的引用计数+1;此时拷贝出来的对象原对象的所占的空间大小相等,内容也相等
       
//深拷贝
不止拷贝空间和内容,而且从新开辟了一块内存
区别:浅拷贝会造成原对象的引用计数加+1,而深拷贝不会造成原对象的计数加+1;
 
 
例子:在Person类基础上举例
Person.h
#import
@interface
Person
: NSObject<</span>NSCopying>必须遵循NSCopying
协议
//名字的属性
@property
(nonatomic,copy)NSString
*name;
@end

Person.m
-
(void)dealloc{
 
NSLog(@"Person%@对象被销毁了",_name);
   
[super
dealloc];
}
-
(id)copyWithZone:(NSZone
*)zone{

   
//返回对象的时候要做一次retain操作,外界的接受者才持有这个对象
    // return [self
retain];
//深拷贝 
返回的是新的对象,此时两个对象所占的空间大小相同,内容也相同

   
Person
*p
= [[Person
allocWithZone:zone]init];
   
p.name
=
self.name;
   
return
p;
}
@end

main.m
 
Person
*p11 =
[[Person
alloc]init];

p11.name
=
@"笙萧默";

Person
*p12 =
[p11 copy];

NSLog(@"%@",p12.name);

       
NSLog(@"p11
= %p p12 = %p ",p11,p12);
 
   
       
kRelease_Safe(p11);
       
kRelease_Safe(p12);
=====================================================
11、 new 
申请创建对象的同时让其引用计数0-—>1(不常用)
       
//new其实就做了alloc和init
两步操作,申请空间并初始化

       
//     
[Person new] = [Person alloc]init];

       
Person
*p13 =
[Person
new];

p13.name
=
@"东方";

       
kRelease_Safe(p13);
总结:内存管理的总结
        
1.引用计数+1(alloc ,copy , new , retain)

        
2.引用计数 -1 (release , autorelease)

        
3.要想内存不出现泄漏,引用计数-1的次数相等

        
4.一旦引用计数为0的时候系统会自动调用dealloc 方法
        
5.谁污染谁治理,谁alloc谁release,谁return谁release,autorelease
欢迎学习本文,未经许可,不得私自转载!

内存管理Memory&nbsp;OC——第九天的更多相关文章

  1. Android 内存管理 &Memory Leak & OOM 分析

    转载博客:http://blog.csdn.net/vshuang/article/details/39647167 1.Android 进程管理&内存 Android主要应用在嵌入式设备当中 ...

  2. SQL Server 2012 内存管理 (memory management) 改进

    SQL Server 2012 的内存管理和以前的版本相比,有以下的一些变化. 一.内存分配器的变化 SQL Server 2012以前的版本,比如SQL Server 2008 R2等, 有sing ...

  3. 内存管理 - MEMORY POOL

    内存池优势: 效率高,频繁的new和delete效率低下 减少内存碎片,反复向系统申请和释放内存会产生大量内存碎片 防止内存泄露 内存池设计思路: 内存池可以根据实际需要,设计成不同的样子.下面是针对 ...

  4. QF——OC内存管理详解

    堆的内存管理: 我们所说的内存管理,其实就是堆的内存管理.因为栈的内存会自动回收,堆的内存需要我们手动回收. 栈中一般存储的是基本数据类型变量和指向对象的指针(对象的引用),而真实的对象存储在堆中.因 ...

  5. oc 第五天(内存管理)

    OC的重点: 内存管理 1 基本原理     OC的内存回收机制是和JAVA的自动回收机制是不同的,它有两种模式,或者准确的说是同 一种模式的两种不同体现,下面简单总结下. 1手动内存回收       ...

  6. OC开发系列-内存管理

    概述 移动设备的内存极其有限,每个app所有占用的内存是有限的.当app所占用的内存比较多时,系统会发出内存警告,这时得回收一些不需要再使用的内存空间. 任何集成了NSObject的对象都需要手动进行 ...

  7. Object-c 内存管理

                    内存管理 主要内容 1.内存管理的概念 2.引用计数 3.如何持有对象所有权 4.自动释放池 5.@property的使用 什么是内存管理 内存管理是关于如何管理对象生 ...

  8. C++中的内存管理

    在C++中也是少不了对内存的管理,在C++中只要有new的地方,在写代码的时候都要想着delete. new分配的时堆内存,在函数结束的时候不会自动释放,如果不delete我分配的堆内存,则会造成内存 ...

  9. OC内存管理(MRC)

    首先说明一下几块存储区域: 栈区(局部变量.函数参数值) 堆区(对象.手动申请/释放内存) BSS区(未初始化的全局变量.未初始化的静态数据) 常量区(字符串常量以及初始化后的全局变量.初始化后的静态 ...

随机推荐

  1. git提交项目常用命令及git分支的用法

    1.第一步首先从git托管平台clone项目,我这里就使用idea为例: 填写git的url与存放本地目录名及项目名     2.如果你对项目进行了一些修改,就可以执行git命令,进行提交. 有两种方 ...

  2. Android RRO机制的运用-----google开机向导客制化

    上周五的时候领导分了一个任务,客户让在google开机向导里面增加一页,首先就想到了android的Overlay,然后网上搜了下,发下有很多人写了这方面的技术.而且写的都还不错,所以本篇只当记录作用 ...

  3. FindBugs入门简介(eclipse安装使用实例)

    前言:一般公司都会有一些开发规范,但是事实上,简单看那么一两遍并不能养成习惯,或者将这些规范记住.特别的,对于一些新手,写的代码往往会很糟糕.回头看看你一两年前写的代码就会知道,所谓的"糟糕 ...

  4. Scala:访问修饰符、运算符和循环

    http://blog.csdn.net/pipisorry/article/details/52902234 Scala 访问修饰符 Scala 访问修饰符基本和Java的一样,分别有:privat ...

  5. springMVC源码分析--AbstractDetectingUrlHandlerMapping(五)

    上一篇博客springMVC源码分析--AbstractUrlHandlerMapping(三)中我们介绍了AbstractUrlHandlerMapping,主要介绍了一个handlerMap的ur ...

  6. ROS机器人程序设计(原书第2版)学习镜像分享及使用说明

    ROS机器人程序设计(原书第2版)学习镜像分享及使用说明 系统用于ROS爱好者学习交流,也可用于其他用途,并不局限于ROS. 这款镜像文件是基于一年前的Ubuntu ROS Arduino Gazeb ...

  7. [Matlab]技巧笔记

    1.将字符串作为Matlab命令执行 md = 'dir'; eval(md); 2.将字符串作为系统命令执行 md = 'dir'; system(md); 3.使显示图像的坐标轴使用相同的度量单位 ...

  8. Hadoop介绍

    是适合大数据的分布式存储与计算平台,用java编写的开源系统,能够安排在大规模的计算机平台上,从而长进计算效率:由 HDFS.MapReduce.HBase.Hive 和 ZooKeeper等成员组成 ...

  9. iOS日历中给一个事件添加多个提醒

    大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请多提意见,如果觉得不错请多多支持点赞.谢谢! hopy ;) iOS自带的日历应用中,我们最多只能给一个事件设置2个提醒,但 ...

  10. 剑指offer面试题4 替换空格(java)

    注:利用java中stringBuilder,append,length方法很方便的解决字符串问题 /* * 剑指offer 替换空格 * xsf * */ /*开始替换空格的函数,length为原数 ...