———————————————————————————————————————————

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方法】的更多相关文章

  1. iOS-旧项目中手动内存管理(MRC)转ARC

    在ARC之前,iOS内存管理无论对资深级还是菜鸟级开发者来说都是一件很头疼的事.我参 加过几个使用手动内存管理的项目,印象最深刻的是一个地图类应用,由于应用本身就非常耗内存,当时为了解决内存泄露问题, ...

  2. Objective-C 【内存管理&手动内存管理 综述】

    ------------------------------------------- 内存管理 (1)Objective-C的内存管理 栈区    存放局部变量(由于基本数据类型占用的存储空间是固定 ...

  3. object-C 手动内存管理(MRC)

    object-C的内存管理和javascript的垃圾回收不一样,今天总结下手动内存管理,ARC的后边补上. 1:基本铺垫 oc采用引用计数来表示对象的状态,比如通过init创建出来的一个对象引用计数 ...

  4. Xcode 如何设置 自动内存管理 转换为 手动内存管理

    建议使用自动内存管理 ARC. 如果不想自动内存管理,可以在build phases 下的compile sources 中找到不想自动管理的.m文件 ,给它加compiler flags 为 -fn ...

  5. 【iOS开发-33】学习手动内存管理临时抛弃ARC以及retain/assign知识——iOSproject师面试必考内容

    我们为什么须要内存管理?当使用内存达到40M和45M时候会发出警告,假设不处理,占用内存达到120M时直接强制关闭程序. 所以出现闪退除了是程序出现逻辑错误,还有可能是内存使用过大. (1)创建一个对 ...

  6. Objective -C Memory Management 内存管理 第一部分

    Objective -C Memory Management  内存管理  第一部分 Memory management is part of a more general problem in pr ...

  7. IOS基础 Day-1手动内存管理

    辞职回家打算自学IOS开发,就在借个地方记录一下 Day-1      手动内存管理                   主要内容:release  retain必须配对好,不然会占用内存 慢慢积累导 ...

  8. swift内存管理中的引用计数

    在swift中,每一个对象都有生命周期,当生命周期结束会调用deinit()函数进行释放内存空间. 观察这一段代码: class Person{ var name: String var pet: P ...

  9. OC 内存管理之手动内存管理MRC

    一.基本原理 1.什么是内存管理 内存管理的重要性: 移动设备的内存极其有限,每个app所能占用的内存是有限制的 当app所占用的内存较多时,系统会发出内存警告,这时得回收一些不需要再使用的内存空间. ...

随机推荐

  1. Flex “跑马灯”效果(自定义“跑马灯”控件)

    自定义类(BroadCastMarquee.as): package marquee { import flash.events.MouseEvent; import flash.events.Tim ...

  2. uva11324 The Largest Clique --- 强连通+dp

    给一个有向图G,求一个子图要求当中随意两点至少有一边可达. 问这个子图中最多含多少个顶点. 首先找SCC缩点建图.每一个点的权值就是该点包括点的个数. 要求当中随意两点可达,实际上全部边仅仅能同方向, ...

  3. NAT的全然分析及其UDP穿透的全然解决方式

    NAT的全然分析及其UDP穿透的全然解决方式   一:基本术语 防火墙 防火墙限制了私网与公网的通信,它主要是将(防火墙)觉得未经授权的的包丢弃,防火墙仅仅是检验包的数据,并不改动数据包中的IP地址和 ...

  4. Codeforces Round #327 (Div. 2) A. Wizards' Duel 水题

    A. Wizards' Duel Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/591/prob ...

  5. 2015南阳CCPC E - Ba Gua Zhen 高斯消元 xor最大

    Ba Gua Zhen Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 无 Description During the Three-Kingdom perio ...

  6. Codeforces Gym 100342D Problem D. Dinner Problem Dp+高精度

    Problem D. Dinner ProblemTime Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/1003 ...

  7. C# 图片保存到数据库和从数据库读取图片并显示

    图片保存到数据库的方法: public void imgToDB(string sql)        {   //参数sql中要求保存的imge变量名称为@images            //调 ...

  8. [安卓学习]AndroidManifest.xml文件内容详解

    一,重要性 AndroidManifest.xml是Android应用程序中最重要的文件之一.它是Android程序的全局配置文件,是每个 android程序中必须的文件.它位于我们开发的应用程序的根 ...

  9. win7中USB音箱没有声音解决的方法

    Win7装好后,原来在XP中工作正常的USB小音箱却不工作了,重装了声卡驱动还是一样,后来通过下面尝试最终好用了. 1.右键右下角喇叭button. 2.点击"播放设备". 3.设 ...

  10. printf, fprintf, sprintf, snprintf, vprintf, vfprintf, vsprintf, vsnprintf - 输出格式转换函数

    参考:http://blog.sina.com.cn/s/blog_674b5aae0100prv3.html 总览 (SYNOPSIS) #include <stdio.h> int p ...