zoukankan      html  css  js  c++  java
  • Objective-C知识总结(3)

    手动内存管理MRC

    首先介绍一下引用计数器:用来保存当前对象有几个东西在使用它(数字)

    引用计数器的作用:用来判断对象是否应该回收内存空间(如果对象不等于nil,当引用计数器为0,此时要回收对象的内存空间)

    引用计数器的操作:

    • retain    使得引用计数器+1

    • release   使的引用计数器-1

    • retainCount  得到引用计数器的值

    如果一个对象被释放的时候,会调用该对象的dealloc方法

    注意:

    • dealloc方法是NSObject 的,一般我们要重写dealloc方法
    • 在dealloc 方法的内部,要调用 [super dealloc];

    内存管理的范围:

    • 所有的集成了NSObject的对象的内存管理

    • 基本数据类型(int double float char struct enum )的数据内存不需要我们进行管理

    内存管理的原则:

    1. 如果对象有人使用,就不应该回收  

      如果你想使用这个对象,应该让这个对象 retain一次  

      如果你不想使用这个对象了,应该让这个对象 relase一次

    2. 谁创建 谁release

    3. 谁 retain 谁 release

    内存管理研究的内容:

    1. 野指针:

        1)定义的指针变量没有初始化     2)指向的空间已经被释放

    2. 内存泄露:

      {
                   Person *p  = [Person new];
       
                   }
      /*
                   p 栈区
                   [Person new];  堆区
       
                   如果栈区的p已经释放了,而堆区的空间还没有释放,堆区的空间就被泄露了
      */

    set方法内存管理

    //  Dog* _dog;
     
    //  对于对象作为另外一个类的实例变量
     
    - (void)setDog:(Dog*)dog {
     
     //  判断对象是否是原对象
            if(_dog != dog) {
     
               //2) release旧值
               [_dog release];
     
                // retain 新的值,并且赋值给实例变量
               _dog = [dog retain];
            }
        }

    循环retain问题

    循环的retain 会导致两个对象都会内存泄露

    防止方法:

    1. 让某个对象多释放一次 (注意顺序)

    2. 一端使用 assign   一端使用retain(推荐使用)

    NSString类的内存管理问题

    #import <Foundation/Foundation.h>
    
    int main(int argc, const char * argv[]) {
        @autoreleasepool {
            
            //定义字符串
            //字符串的常量池,
            //如果你需要的字符串在常量池中已经存在了,不会分配内存空间
            //使用字符串的时候,
            // @"abc"  stringWithString    alloc initWithString  都在常量区/
            
            //0x100001030 小
            NSString *str1 = @"abc";   //@"abc" 字符串的常量
            NSString *str3 = [NSString stringWithString:@"abc"];   //常量区
            NSString *str5 = [[NSString alloc] initWithString:@"abc"]; //也在常量区
            NSString *str6 = [[NSString alloc] init];//常量区
            str6 = @"abc";
    
            
            //0x100202030 大
            //如果在常量区 str2  str4 地址应该是一样的
            //实际上不一样的,所以 str2 str4都在堆区
            NSString *str2 = [NSString stringWithFormat:@"abc"];   //不是在栈区,在堆区
            NSString *str4 = [[NSString alloc] initWithFormat:@"abc"];//不是在栈区,在堆区
            
            
            //0x7fff5fbff764
            int a = 10;  //栈区
            
            NSLog(@"str1 = %@,%p,%lu",str1,str1,str1.retainCount);
            NSLog(@"str2 = %@,%p,%lu",str2,str2,str2.retainCount);
            NSLog(@"str3 = %@,%p,%lu",str3,str3,str3.retainCount);
            NSLog(@"str4 = %@,%p,%lu",str4,str4,str4.retainCount);
            NSLog(@"str5 = %@,%p,%lu",str5,str5,str5.retainCount);
            NSLog(@"str6 = %@,%p,%lu",str6,str6,str6.retainCount);
            NSLog(@"a = %p",&a);
            
            
        }
        return 0;
    }

    自动释放池 :特殊的栈结构

    特点: 

    • 对象可以加入到自动释放池中
    • 自动释放池结束的时候,会给池中的对象发送一条 release消息

    自动释放池的使用:

    1. 创建自动释放池
          @autoreleasepool {
    
          }

         2.  加入自动释放池

    /*
      在自动释放池中
      [对象  autorelease];
    */

    模拟一个Person类 类中有个一个对象方法- (void)run;

    #import <Foundation/Foundation.h>
    #import "Person.h"
    int main(int argc, const char * argv[]) {
        //1 创建自动释放池
        Person *p = [Person new];  // p  1
        @autoreleasepool {//自动释放池开始
            
            [p run];
     
            NSLog(@"%lu",p.retainCount); // 1
            
            // [p autorelease] 把对象p加入到自动释放池中
            // 注意:加入到自动释放池中以后, 引用计数不会变化
            [p autorelease];  //加入自动释放池,
            NSLog(@"%lu",p.retainCount); // 1
            
            [p run];
            
        }//自动释放池结束   [p release];
        [p run];
        return 0;
    }

     我们可以给Person添加一个类方法,让其创建完对象就加入到自动释放池中

    +(instancetype)person{
        //Person person  ---> Person
        //Stduent person ----> Student
        //创建对象
        return [[[self alloc] init] autorelease];  // 返回的时对象的空间
        // 能够帮我们把对象给加入到自动释放池
    
    }

         

  • 相关阅读:
    从句分析
    artDialog ( v 6.0.2 ) content 参数引入页面 html 内容
    Java实现 LeetCode 13 罗马数字转整数
    Java实现 LeetCode 13 罗马数字转整数
    Java实现 LeetCode 13 罗马数字转整数
    Java实现 LeetCode 12 整数转罗马数字
    Java实现 LeetCode 12 整数转罗马数字
    Java实现 LeetCode 12 整数转罗马数字
    Java实现 LeetCode 11 盛最多水的容器
    Java实现 LeetCode 11 盛最多水的容器
  • 原文地址:https://www.cnblogs.com/melodyzhy/p/4678759.html
Copyright © 2011-2022 走看看