zoukankan      html  css  js  c++  java
  • OC第三天(内存管理)

    内存管理:

    1.作用范围:

    不论什么继承了NSObject的对象,堆基本数据类型无效如:int a ,float price;;

    2.原理:

    每一个对象内部都保存了一个与之相关的整数,称为引用计数器,

    当使用alloc   new   copy创建一个对象的时候,对象的引用计数器被设置为1

     

    每给对象发送一次retain消息。能够使引用计数器+1

    给对象发送一条release消息。能够使引用计数器-1

     

    当一个对象的引用计数器为0时,那么它将被销毁。其占用的内存被系统回收,OC也会自己主动向对象发送一条dealloc消息,通常会重写dealloc方法,在这里,释放相关资源,一定不要直接调用dealloc方法:

     

    能够给对象发送retaincount消息。获得当前的因数计数器数值。

     

     

     

    3.retain release

    1。假设你想知道一个对象是不是被回收,方法:重写父类的dealloc方法:

    注意:一定要调用super的dealloc方法,并且最后放在最后面调用。

    ([super dealloc ])

     

    2.假设一个对象调用了release 的操作。而且他的引用计数器已经为0。假设你再次调用他的release方法:这时候就会发生野指针错误:

    野指针错误:你调用了本不属于你的内存空间,你既然已经释放了本来你的内存,那么如今那块内存已经不属于你了。你在调用release方法。说明你又声明那块内存是属于你的,这时候就会发生野指针 错误。

     

    注意:当一个对象retain0的时候。这时候你就不能再调用他的retainCound方法。由于一个被释放的对象,没有内存。不再去进行訪问会发生野指针错误。

     

    3.假设你在创建对象的时候。加上autorelease,那么编译器会在一个适当的时机释放对象,这                     样就不须要你自己手动释放对象的内存了

     

     

    4.内存管理法则:

    1.谁创建,谁释放(“谁污染,谁治理”),假设你通过alloc ,new ,copy来创建一个对象。那么你必须调用release或autorelease ,假设不是你创建的。你就不用去释放。

    2.一般除了alloc ,new  copy之外的方法创建的对象都被声明了autorelease

    3.retain ,谁release ,仅仅要你调用了retain ,不管这个对象是怎样产生的,你都要调用release;

     

     

    5.对象之间的内存管理:

    前提:假设一个类A作为另外一个类B的成员变量。而且訪问A的数据成员的是否。假设在main函数中调用了类B的一个方法,这时候会调用A的对象进行初始化A的成员变量,当在该方法中销毁后。类B又訪问了一个方法2,这时候仍然让类A的对象进行初始化操作。这时候会出现野指针错误,

    原因:因为在方法1中已经释放了A对象,所以A对象所指向的成员变量的内存回收,假设你再进行调用。就会指向一个不属于自己的内存空间,这是非常危急的。

     

    解决的方法。在set方法里里面设施对象的retain操作。并进行release。前提。是推断传进来的对象是不是本身。假设是本身那就释放掉原来对象的指向,假设是一个新的,那就没有必要进行release,由于,新对象本来计数器为0.你再release,就会错误。

    代码例如以下:

    B 中的.M文件

    - (id)initWithAge:(int)age{

       if ( self= [super init]) {

           _age = age;

       }

       

        return self;

    }

     

    #pragma mark 回收对象

    - (void)dealloc {

        // 释放Book对象

       [_book release];

       

        //[self.book release];

       

        NSLog(@"student:%i被销毁了", _age);

       [super dealloc];

    }

     

    #pragma mark - gettersetter

     

    - (void)setBook:(Book*)book {

       if (_book!= book) {

            // 先释放旧的成员变量

           [_book release];

            // retain新传进来的对象

           _book = [book retain];

       }

    }

     

    - (Book *)book {

       return _book;

    }

     

    #pragma mark - 公共方法

    #pragma mark 读书

    - (void)readBook {

        NSLog(@"当前读的书是:%f", _book.price);

    }

     

     

     

    main函数:

    void test(Student*stu) {

        // book:1  引用计数器

       Book *book = [[Book alloc] initWithPrice:3.5];

     

        // book:2

       stu.book = book;

     

        // book:1

       [book release];

           

         //book2:1

       Book *book2 = [[Book alloc] initWithPrice:4.5];

         //book2:2

       stu.book = book2;

        // book2:2

       stu.book = book2;

        // book2:1

       [book2 release];

       

        // book2:1

        stu.book = book2;//假设再次调用,book2的retaiin也不会变

    }

     

    void test1(Student*stu) {

       [stu readBook];

    }

     

    int main(intargc, const char* argv[])

    {

     

        @autoreleasepool {

           // stu:1

           Student *stu = [[Student alloc] initWithAge:10];

           

           // stu:1

            //book:1

            //book2:1

           test(stu);

           

           // stu:1

            //book:1

            //book2:1

           test1(stu);

           

           // stu:0

            //book2:0

            //book:1

           [stu release];

       }

       return 0;

    }

     

  • 相关阅读:
    姚明如何理财
    转:韩国“抢文化”与中国的“文化洁癖”
    转:关于IDL程序的发布
    GIS相关网站
    【转】:身为男人应做的十件事情
    转:关于稀少控制点下遥感影像纠正的主要研究成果
    转:E都市创业经历
    转载:OSSIM简介
    市场营销学课程
    C#中判断是否为数字&是否为整除(转)
  • 原文地址:https://www.cnblogs.com/gavanwanggw/p/7084668.html
Copyright © 2011-2022 走看看