Objective-C 【在手动内存管理中如何写set方法】
———————————————————————————————————————————
set方法的内存管理
代码:
#import <Foundation/Foundation.h>
@interface Car : NSObject
-(void)run;
@property int speed;
@end
@implementation Car
-(void)run
{
NSLog(@"car run!");
}
- (void)dealloc
{
NSLog(@"car dealloc!");
[super dealloc];
}
@end
@interface Person : NSObject
{
Car *_car;
}
-(void)driver;
-(void)setCar:(Car *)car;
@end
@implementation Person
//test1中运用到的set方法
//-(void)setCar:(Car *)car
//{
// [_car release];//release一下原来的内存(注意:如果是第一次调用set方法,_car里面是nil,nil!=car,不过此时也是可以调用[_car release];的,只是不起作用罢了~)
// _car=[car retain];//给car的计数+1,然后赋给_car(如果是第一次set,那么为什么这里要retain呢,因为必须让计数等于2,因为在main函数里,我们在[p release]; 和 [car release];各释放了一次car,所以-2的前提是要+2)
//}
//改进后的set方法
-(void)setCar:(Car *)car
{
// 如果 _car 和 car 相等,那么就无需做任何操作了,因为之前已经做过一次setCar了。如果对原值操作release和retain。那么就会出现野指针(“僵尸对象复活”)。所以只有传入的值和先前的值不一样,才会做下列操作:①release原值 ②_car=car; ③retain新值
if (_car!=car) {
[_car release];
_car=[car retain];
}
}
-(void)driver
{
[_car run];
}
- (void)dealloc
{
[_car release];//上节知识点,我们之前在setCar里面retain car了一次,所以必须让car的计数减1.所以要再Person里有Car的实例变量,若要释放car的内存,在Person的dealloc里面可以做到这一点。但是我们就没法在Car的dealloc里面释放Person了。
NSLog(@"person dealloc!");
[super dealloc];
}
@end
//在test1中暂时保存~需要时拿出来运行检验
void test1()
{
// set方法的内存管理(1)———— 原对象无法被释放造成的内存泄漏问题
// 创建Person的实例对象p
Person *p=[[Person alloc]init];//p 1
// 创建Car的实例对象car1
Car *car1=[[Car alloc]init];//car1 1
car1.speed=120;
// 将car1赋给p(p拥有了第一辆车car1)
[p setCar:car1];//car1 2(在set方法中retain了一下)
[p driver];//想要driver,就要给p的Car赋值~(你要先给他一辆车)
[car1 release];//car1用完了我们可以将car1释放掉,car1 1
// 创建Car的实例对象car2
Car *car2=[[Car alloc]init];//car2 1
// 将car2赋给p(p拥有的第二辆车car2)
[p setCar:car2];//car2 2
// 我们知道,在setCar中是这么一句话:_car=[car retain]; 在此处,没运行这句话之时,因为之前曾经调用的setCar,所以_car中存的是car1的内存地址。而运行到此处_car又变为了新的car2,car2变成了2,而car1还是1没变。
[car2 release];//car2 1
[p release];//p 0 car2 0 car1 1
// 这样看来,因为_car中的内存地址在两次setCar中发生了改变,导致本来意图在[p release]的同时想要[car1 release],却[car2 release]
// 这样导致car1的内存没有释放完毕,所以导致的内存泄漏,那么我们就应该在setCar 传入第二个值的时候先将第一个值释放(也就是此时_car中保存的地址release掉,这样就不会造成car1的内存泄漏)
}
int main(int argc, const char * argv[]) {
@autoreleasepool {
// set方法的内存管理(2)———— 同一个实例变量set两次,出现野指针(“僵尸对象复活”)
Person *p2=[[Person alloc]init];//p2 1
Car *car3=[[Car alloc]init];//car3 1
[p2 setCar:car3];//car3 2 (_car里面目前存的是car3的地址)
[p2 driver];
[p2 setCar:car3];//如果说setCar对同一个实例变量进行操作,也就是将car3 setCar了两次,那样的话car3 3 ,那样的话必然会造成car3的内存泄漏,所以说我们有必要进行一个if语句的判断,也就是如果传进来的参数地址和_car中的地址一致,那么就没有必要进行retain了。于是我们可以改进一下set方法。
[car3 release];
[p2 release];
/*
set方法的内存管理(3)———— set的写法(在手动管理内存的情况下)
(1)基本数据类型
-(void)setSpeed:(int)speed
{
_speed=speed;
}
(2))OC对象
-(void)setCar:(Car *)car
{
//①先判断_car和car表示的地址是否一致(也就是先看car是不是新传来的对象)
if(_car!=car)
{
//②对旧对象做一次release
[_car release];
//③对新对象做一次retain
_car=[car retain];
}
}
*/
}
return 0;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。
Objective-C 【在手动内存管理中如何写set方法】的更多相关文章
- iOS-旧项目中手动内存管理(MRC)转ARC
在ARC之前,iOS内存管理无论对资深级还是菜鸟级开发者来说都是一件很头疼的事.我参 加过几个使用手动内存管理的项目,印象最深刻的是一个地图类应用,由于应用本身就非常耗内存,当时为了解决内存泄露问题, ...
- Objective-C 【内存管理&手动内存管理 综述】
------------------------------------------- 内存管理 (1)Objective-C的内存管理 栈区 存放局部变量(由于基本数据类型占用的存储空间是固定 ...
- object-C 手动内存管理(MRC)
object-C的内存管理和javascript的垃圾回收不一样,今天总结下手动内存管理,ARC的后边补上. 1:基本铺垫 oc采用引用计数来表示对象的状态,比如通过init创建出来的一个对象引用计数 ...
- Xcode 如何设置 自动内存管理 转换为 手动内存管理
建议使用自动内存管理 ARC. 如果不想自动内存管理,可以在build phases 下的compile sources 中找到不想自动管理的.m文件 ,给它加compiler flags 为 -fn ...
- 【iOS开发-33】学习手动内存管理临时抛弃ARC以及retain/assign知识——iOSproject师面试必考内容
我们为什么须要内存管理?当使用内存达到40M和45M时候会发出警告,假设不处理,占用内存达到120M时直接强制关闭程序. 所以出现闪退除了是程序出现逻辑错误,还有可能是内存使用过大. (1)创建一个对 ...
- Objective -C Memory Management 内存管理 第一部分
Objective -C Memory Management 内存管理 第一部分 Memory management is part of a more general problem in pr ...
- IOS基础 Day-1手动内存管理
辞职回家打算自学IOS开发,就在借个地方记录一下 Day-1 手动内存管理 主要内容:release retain必须配对好,不然会占用内存 慢慢积累导 ...
- swift内存管理中的引用计数
在swift中,每一个对象都有生命周期,当生命周期结束会调用deinit()函数进行释放内存空间. 观察这一段代码: class Person{ var name: String var pet: P ...
- OC 内存管理之手动内存管理MRC
一.基本原理 1.什么是内存管理 内存管理的重要性: 移动设备的内存极其有限,每个app所能占用的内存是有限制的 当app所占用的内存较多时,系统会发出内存警告,这时得回收一些不需要再使用的内存空间. ...
随机推荐
- java中的hashcode和euqals的区别和联系
一.equals方法的作用 1.默认情况(没有覆盖equals方法)下equals方法都是调用Object类的equals方法,而Object的equals方法主要用于判断对象的内存地址引用是不是同一 ...
- cmp排序hdoj 1106排序
上班之余抽点时间出来写写博文,希望对新接触的朋友有帮助.今天在这里和大家一起学习一下cmp排序 /*标题还是比拟的水吧,但是花的时间还是比拟的多,心不够静*/ #include <iostrea ...
- UVa 1252 - Twenty Questions(记忆化搜索,状态压缩dp)
本文出自 http://blog.csdn.net/shuangde800 题目链接:点击打开链接 题目大意 有n个长度为m的二进制串,每个都是不同的. 为了把所有字符串区分开,你可以询问,每次可 ...
- thinkphp中的HTTP类实现下载
public function test(){ import('ORG.Net.Http'); $filename="Uploads/v1.2.doc"; //exit($file ...
- Python的包管理工具Pip
接触了Ruby,发现它有个包管理工具RubyGem非常好用,而且有非常完备的文档系统http://rdoc.info 发现Python下也有相同的工具,包含easy_install和Pip.只是,我没 ...
- aspose.cells 模版
aspose.cells 模版 http://www.cnblogs.com/whitewolf/archive/2011/03/21/Aspose_Cells_Template1.html
- SAP BW 通过视图创建数据源(无单位)
因业务明细表中数量没有单位,所以BW创建数据源时,需做增强 数据表: ZDB_H(抬头) ZDB_I(明细) ECC 系统中: 1.创建视图ZVDBWQ,因明细表中数量没有单位,所以创建视图时不包括数 ...
- MHA自动Failover过程解析(updated) 转
允许转载, 转载时请以超链接形式标明文章原始出处和网站信息 http://www.mysqlsystems.com/2012/03/figure-out-process-of-autofailover ...
- win7配置nginx + php
nginx的下载地址: http://www.nginx.cn/nginx-download 在nginx下创建文件php-cgi.cmd,并写入内容: "D:\nginx_php-5.6 ...
- win7引导项顺序
转载:http://jingyan.baidu.com/article/72ee561aa1d123e16138df81.html 问题描述: 个人在宿舍使用的比较多的是Window 7,而它的启动项 ...