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;

    }

     

  • 相关阅读:
    Saltstack module acl 详解
    Saltstack python client
    Saltstack简单使用
    P5488 差分与前缀和 NTT Lucas定理 多项式
    CF613D Kingdom and its Cities 虚树 树形dp 贪心
    7.1 NOI模拟赛 凸包套凸包 floyd 计算几何
    luogu P5633 最小度限制生成树 wqs二分
    7.1 NOI模拟赛 dp floyd
    springboot和springcloud
    springboot集成mybatis
  • 原文地址:https://www.cnblogs.com/gavanwanggw/p/7084668.html
Copyright © 2011-2022 走看看