oc-31-多对象的内存管理
在每个OC对象内部,都专门有8个字节的存储空间来存储引用计数器。
引用计数器的常见操作
retain消息:堆内存中对象的计数器变量 +(该方法返回对象本身,要想计数器变量加1就要调用对象的retain方法)
release消息: 堆内存中对象的计数器变量 -(不代表释放对象,要想计数器变量减1就要调用对象的release方法)
retainCount:获得对象当前的应用计数器值,输出:%ld %lu,NSLog(@"%lu",h.retainCount);
注意:release不代表销毁对象,仅仅是引用计数器- .谁创建,谁release )如果你通过alloc,new,copy来创建了一个对象,那么你就必须调用release或者 autorelease方法.
)不是你创建的就不用你去负责
.谁retain,谁release 只要你调用了retain,无论这个对象时如何生成的,你都要调用release )对象的销毁 当1个对象的应用计数器为0时,那么它将被销毁,其占用的内存被系统回收。
当对象被销毁时,系统会自动向对象发送一条dealloc消息。一般会重写dealloc方法,在这里释放相关的资源,dealloc就像是对象的“临终遗言”。
一旦重写了dealloc方法,就必须调用[super dealloc],并且放在代码块的最后调用。
注意:不能直接调用dealloc方法。
一旦对象被回收了,那么他所占用的存储空间就不再可用,坚持使用会导致程序崩溃(野指针错误) 注意; ) 如果对象的计数器不为0,那么在整个程序运行过程,它占用的内存就不可能被回收(除 非整个程序已经退出 )
)任何一个对象,刚生下来的时候,引用计数器都为1。(对象一旦创建好,默认引用计数器就是1)当使用alloc、new或者copy创建一个对象时,对象的引用计数器默认就是1. 、内存管理的分类 Objective-C提供了三种内存管理方式: .MannulReference-Counting(MRC,手动管理,在开发iOS4.1之前的版本的项目时我们要自己负责使用引用计数来管理内存,比如要手动 retain、release、autorelease 等,而在其后 的版本可以使用 ARC,让系统自己管理内存。)
.automatic reference-counting(ARC,自动引用计数,iOS4.1之后推出的)
.garbage collection(垃圾回收)。iOS不支持垃圾回收; ARC作为苹果新提供的技术,苹果推荐开发者使用ARC技术来管理内存; 开发中如何使用:需要理解MRC,但实际使用时尽量用ARC。
Gamer.h
#import <Foundation/Foundation.h>
#import "House.h" @interface Gamer : NSObject
{
House *_house; // 房间,游戏玩家在哪里房间
}
- (void)setHouse:(House *)house;
- (House *)house;
//@property House *house;
@end
Gamer.m
#import "Gamer.h" @implementation Gamer
- (void)dealloc
{
NSLog(@"玩家被释放");
// 当玩家自己被回收时,对房间进行一次release操作减少堆内存中对象的计数器变量值.
[_house release];
[super dealloc];
} - (void)setHouse:(House *)house
{
if (_house != house) {
//当玩家换房间时,需要对旧房间做一次release操作减少堆内存中对象的计数器变量值
[_house release];
// 玩家要进入房间,玩家就要对房间进行一次retain操作增加堆内存中对象的计数器变量值.
_house = [house retain];
}
}
- (House *)house
{
return _house;
}
@end /*
// 1、创建玩家对象
Gamer *game = [[Gamer alloc] init];
// 2、创建房间对象
Room *room = [[Room alloc] init];
// 3、让玩家进入房间
game.room = room;//堆中对象的计数器变量没有加1因为没有调用retain方法,
// 4、释放房间对象
[room release];
// 5、输出玩家的房间
NSLog(@"玩家的房间是:%@",game.room);
此时,会报野指针错误。 解决方案:
,对房间进行一次retain。
// 声明类
@interface Gamer : NSObject
{
Room *_room;
}
- (void)setRoom:(Room *)room;
- (Room *)room; // 实现类
@implementation Gamer
- (void)setRoom:(Room *)room
{ [room retain];//堆中对象的计数器变量加1后赋值
_room = room;
}
- (Room *)room{
return _room;
} 问题:房间无法被释放了怎么办?
解决方法:
在对象被释放时,要把该对象的所有对象类型的成员变量在dealloc当中进行释放:
@implementation Gamer
- (void)dealloc
{
[_room release];//堆中对象的计数器变量减1
NSLog(@"玩家被释放");
[super dealloc];
}
@end 解决方案:判断新进房间与之前是否是同一个房间。
- (void)setRoom:(Room *)room
{
if (_room != room) {
// 释放旧房间
[_room release];
[room retain];//加1后赋值
_room = room; }
} 总的来说,有以下几点规律:
2)只要想要使用1个对象,那么就让对象的引用计数器+1。
3)当不再使用这个对象时,就让对象的引用计数器-1。 需求:
1、让玩家换房间,进入1号房间后,再进入2号房间
// 实现玩家类
@implementation Gamer
- (void)setRoom:(Room *)room
{
[_room release];//旧房间的计数器变量减1
_room = [room retain];//新房间的计数器变量加1后赋值
}
- (Room *)room{
return _room;
}
- (void)dealloc
{
[_room dealloc];
NSLog(@"玩家被释放");
[super dealloc];
}
@end
int main(){
// 1、创建玩家对象
Gamer *game = [[Gamer alloc] init];
// 2、创建房间对象
Room *room = [[Room alloc] init];
room.no = 1;
Room *room1 = [[room alloc] init];
room.no = 2;
// 3、让玩家进入房间
game.room = room;
game.room = room1;
// 4、释放房间对象
[room release];
// 5、释放玩家对象
[game release];
return 0;
} 总结:
1、set方法的内存管理
- (void)setRoom:(Room *)room
{
if(_room != room){
[_room release];
_room = [room retain];
}
}
2、dealloc方法内存管理
- (void)dealloc
{
// 当玩家不在了,代表不用房间了
// 对房间进行一次release
[_room release];
// 重写dealloc方法,必须在最后调用父类的dealloc方法
[super dealloc];
}
House.h
#import <Foundation/Foundation.h> @interface House : NSObject
@property int no;
@end
Huose.m
#import "House.h" @implementation House
- (void)dealloc
{
NSLog(@"%d房间被释放了",_no);
[super dealloc];
}
@end
main.m
/**
知识回顾:
什么是内存管理:
管理堆区的内存的分配和释放.
分配内存:new alloc copy
释放内存:release 操作内存的方式:
1)retainCount:获取对象的计数器的值
2)retain:堆内存中对象的计数器变量 +1
3)release:堆内存中对象的计数器变量 -1 僵尸对象:已经被释放的对象
野指针:指向僵尸对象的指针
空指针:nil,给空指针发送消息不会报错. 单个对象的内存管理
Person *p = [[Person alloc] init]; // 计数器 1
[p retain]; // 计数器 2
[p retain]; // 3
//想让p对象释放,怎么办?
// 再做3次release
[p release];
[p release];
[p release]; 一个对象是否被释放,通过什么方式确定?
通过是否调用dealloc方法,在重写dealloc方法时,必须在最后的位置调用[super dealloc]; 多对象内存管理:
1.模拟1个玩家进入1个房间的过程.
分析:类:玩家,房间类,让玩家拥有一间房 2.换房间的一个过程,玩家先进入10号房间,再进入20号房间.此时有什么问题?
解决方法:
在换房间时,需要release旧值,retain新值. */
#import <Foundation/Foundation.h>
#import "Gamer.h" int main(int argc, const char * argv[]) {
@autoreleasepool {
Gamer *g = [[Gamer alloc] init]; //g 1 House *h = [[House alloc] init]; //h 1
//g.house = h只是表示h变量多了一个引用的指向,[[House alloc] init]对象任然只有一个引用,因为没有调用retain方法所以计数器变量不会加1.
// g.house调用了g的setHouse方法所以此时[[House alloc] init]对象的引用为2
g.house = h; [h release]; // h 1 g.house = h; // 再重写进入房间 NSLog(@"%lu",h.retainCount); }
return ;
}
// 换房间
void demo()
{
Gamer *game = [[Gamer alloc] init]; // game :1 House *house = [[House alloc] init]; // house :1
house.no = ; House *house2 = [[House alloc] init];
house2.no = ; House *house3 = [[House alloc] init];
house3.no = ; // 让人进入10号房
game.house = house; // 让人进入20号房间
game.house = house2; // 让人进入20号房间
game.house = house3; // 释放房间
[house release];
[house2 release];
[house3 release];
[game release]; }
oc-31-多对象的内存管理的更多相关文章
- OC语言-05-OC语言-内存管理
一.引用计数器 1> 栈和堆 栈 ① 主要存储局部变量 ② 内存自动回收 堆 ① 主要存储需要动态分配内存的变量 ② 需要手动回收内存,是OC内存管理的对象 2> 简介 作用 ① 表示对象 ...
- OC第七节——内存管理
戏言: iOS开发已经到了一个ARC时代,一般不需要我们过多的去关注内存是怎么分配,怎么管理的.很长一段时间,我也不知道内存管理是什么鬼,但如果遇到这方面的问题,却找不到解决办法确实很头疼的.So,还 ...
- OC基础15:内存管理和自动引用计数
"OC基础"这个分类的文章是我在自学Stephen G.Kochan的<Objective-C程序设计第6版>过程中的笔记. 1.什么是ARC? (1).ARC全名为A ...
- oc 第五天(内存管理)
OC的重点: 内存管理 1 基本原理 OC的内存回收机制是和JAVA的自动回收机制是不同的,它有两种模式,或者准确的说是同 一种模式的两种不同体现,下面简单总结下. 1手动内存回收 ...
- 七.OC基础加强--1.内存管理 2.野指针,内存泄露 3.set方法的内存管理 4.@property参数 5.@class和循环retain的使用 6.NSString的内存管理
1,内存管理简单介绍 1,为什么要有内存管理? malloc selloc dealloc```需要回头复习 一般的内存 4s 是512m内存:6 是1024m内存: 当内存过大时,会耗尽内存.出现程 ...
- OC学习篇之---内存管理介绍和使用
在之前的一片文章我们说了OC中谓词操作:http://blog.csdn.net/jiangwei0910410003/article/details/41923507,从今天开始我们就来看一下OC中 ...
- C++解析(31):自定义内存管理(完)
0.目录 1.遗失的关键字mutable 2.new / delete 3.new[] / delete[] 4.小结 5.C++语言学习总结 1.遗失的关键字mutable 笔试题: 统计对象中某个 ...
- oc学习之路----内存管理
直接上图啊.
- OC开发系列-内存管理
概述 移动设备的内存极其有限,每个app所有占用的内存是有限的.当app所占用的内存比较多时,系统会发出内存警告,这时得回收一些不需要再使用的内存空间. 任何集成了NSObject的对象都需要手动进行 ...
- OC内存管理(MRC)
首先说明一下几块存储区域: 栈区(局部变量.函数参数值) 堆区(对象.手动申请/释放内存) BSS区(未初始化的全局变量.未初始化的静态数据) 常量区(字符串常量以及初始化后的全局变量.初始化后的静态 ...
随机推荐
- 黑马程序员——有关protocol代理模式的举例说明
学习了protocol协议的基本原理和使用方法之后 ,下面就看一下在程序中是怎么体现这种代理思想的. 假定有个人jack需要找一个厨师为自己做饭,当他想要吃饭的时候就可以让厨师给他做好饭.这一需求如何 ...
- 转 Flash与PS交互动画
FLASH是可以点击体验的,不是图片哦. UI中国不能上传flash,但是站酷可以,UI中国的就下载载附件看看吧 本人学生党兼网页设计师菜鸟一名,因为无聊练习做了个FLASH的交互 所以很多学弟学妹们 ...
- 开着奥迪做Uber司机是什么心态?
滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...
- 关于iTunes11.1 不能刷自制固件的解决方案
由于iTunes升级到11.1后, 苹果在程序里限制了不允许刷自制固件, 所以想刷自制固件暂时只能降级iTunes到11.1版本之前, 这里提供iTunes 11.0.5 的下载地址: Windows ...
- True or False
任何对象都可以被测试真值.用于if或while条件中或作为下面的布尔操作的操作数.以下值被视为假: None False 任何数值类型的零,例如,0.0.0.0j . 任何空序列,例如,". ...
- HDU 5707 Combine String (DP,LCS变形)
题意:给定三个字符串,问你第三个是不是由第一个和第二个组成的. 析:当时比赛是没有做出来啊...一直WA,就是没有判断长度,第一个和第二个和是不是和第三个一样,这个忘记... 我们用d[i][j]表示 ...
- C# JackLib系列之Form窗体的ShowWithoutActivation属性及其作用
代码改变世界! 如果要显示顶级窗口,但又不希望由于将输入焦点从当前窗口移开而中断用户的工作,请使用此属性.它可以是一个信息性弹出窗口或浮动窗口,如“画图”应用程序中的“工具”调色板. 由于此属性为只读 ...
- class DelegatingFilterProxy
/** * Proxy for a standard Servlet Filter, delegating to a Spring-managed bean that * implements the ...
- mysql index的长度限制
在InnoDB Storage Engine中单独一个列的最大的索引长度为767bytes,utf8字符集中,一个字符占3个字节,所以如果列的类型为char,那么要想在此列上建立索引,此列最多只能有2 ...
- android手机ping不通linux的ip地址
我的linux是装载虚拟机里的,修改虚拟机的网络连接方式为桥接模式即可.