zoukankan      html  css  js  c++  java
  • OC基础 内存管理

    OC基础  内存管理

    我们所了解的c语言内存管理,如下:

    (1)c语言的内存分配:char *p = (char*)malloc(100*sizeof(char));

    (2)c语言的内存释放:free(p);

    c语言内存管理存在的缺陷:

    (1)不释放就会造成内存泄露。

    (2)多次释放就会造成崩溃。

    (3)大型项目中多人对一块内存进行操作时,不能释放内存,因为不知道别人是否还在使用。

    oc语言的内存管理

    1.内存管理

    (1)引用计数。

    (2)内存管理的黄金法则:谁创建谁释放。

    让我们来看一下测试例子:

    #import <Foundation/Foundation.h>
    #import "Student.h"
    
    int main(int argc, const char * argv[])
    {
    
        @autoreleasepool {
            
            //内存管理
            //用引用计数来管理:
            //alloc/retain/copy  引用计数加1
            //release引用计数减1
            //只有使用过alloc/retain/copy,才能调用release
            
            //内存管理的黄金法则--谁创建谁释放
            
            Student *stu = [[Student alloc] init];
            [stu retain];
            [stu retain];
            NSLog(@"%ld",[stu retainCount]);
            Student *stu4 = [stu copy];
            NSLog(@"%ld",[stu retainCount]);
            NSLog(@"%ld",[stu4 retainCount]);
            NSLog(@"%p",stu);
            NSLog(@"%p",stu4);
            
        }
        return 0;
    }

    测试结果:

    2.类的复合中使用setter

    Student类,Student.h文件:

    #import <Foundation/Foundation.h>
    
    @interface Student : NSObject
    
    @end

    Student.m文件:

    #import "Student.h"
    
    @implementation Student
    
    -(NSString *)description
    {
        return @"我是学生";
    }
    
    @end

    Teacher类,Teacher.h文件:

    #import <Foundation/Foundation.h>
    #import "Student.h"
    
    @interface Teacher : NSObject
    {
        Student *_stu;
    }
    
    -(void)setStu:(Student *)stu;
    
    -(Student *)getStu;
    
    -(void)printf;
    
    @end

    Teacher.m文件:

    #import "Teacher.h"
    
    @implementation Teacher
    
    
    //错误方法1:
    //因为stu对象释放掉时,teacher内的_stu就指向了一个未知地址,不再指向原来的stu,所以stu需要retain,得到错误方法2
    //-(void)setStu:(Student *)stu
    //{
    //    _stu = stu;
    //}
    
    
    //错误方法2:
    //因为用另外一个stu2对象赋值的时候,原先的_stu指向的stu1内存地址不会被释放,造成内存泄漏.所以在retain之前需要先释放掉旧的地址空间,得到错误方法3
    //-(void)setStu:(Student *)stu
    //{
    //    _stu = [stu retain];
    //}
    
    //错误方法3:
    //假如调用setStu传入的对象指针是同一个对象,那么[_stu release]之后,stu指向的内存地址的引用计数已经变为0,内存被释放,无法再retain,所以得到正确的方法4
    //-(void)setStu:(Student *)stu
    //{
    //    [_stu release];
    //    _stu = [stu retain];
    //}
    
    //正确的方法4
    //release和retain都要放在if的语句块内,否则也会造成内存泄漏
    -(void)setStu:(Student *)stu
    {
        if(_stu != stu)
        {
            [_stu release];
            _stu = [stu retain];
        }
    }
    
    -(Student *)getStu
    {
        return _stu;
    }
    
    -(void)printf
    {
        NSLog(@"%@",_stu);
    }
    
    @end

    3.数组的内存管理

    数组的内存管理,同样使用内存的黄金法则:

    (1)当我们创建数组的时候,数组会对每个对象进行引用计数加1。

    (2)当我们把数组销毁的时候,数组会对每个对象引用计数减1。

    (3)当我们给数组添加对象的时候,会对对象进行引用计数加1。

    (4)当我们给数组删除对象的时候,会对对象进行引用计数减1。

    总而言之,谁创建谁释放,遵守内存的黄金法则。

    测试例子:

    #import <Foundation/Foundation.h>
    #import "Student.h"
    
    int main(int argc, const char * argv[])
    {
        
        @autoreleasepool {
            
            //数组创建时:对象指针指向的内存地址引用计数加1
            //数组读取对象时:引用计数不变。
        
            Student *stu1 = [[Student alloc] init];
            Student *stu2 = [[Student alloc] init];
            
            NSArray *array = [[NSArray alloc] initWithObjects:stu1,stu2, nil];
        
            Student *stu3 = [array objectAtIndex:0];
            NSLog(@"%ld",[stu1 retainCount]);
            NSLog(@"%ld",[stu3 retainCount]);
            
            NSLog(@"%p",stu1);
            NSLog(@"%p",stu3);
            
        }
        
        return 0;
    }

    测试结果:

    4.自动释放

    (1)系统自动释放池:在runloop循环时,系统判断系统自动释放池内的对象的引用计数,如果为1并且持有对象-1时,就释放对象,不为1时,如果持有对象-1,引用计数就-1,否则引用计数不变。

    (2)自定义的自动释放池,当自动释放池结束时,释放自动释放池内的对象。

  • 相关阅读:
    1. jQuery中的DOM操作
    jQuery查找节点(选择器)
    机器学习基础
    CRF
    NP
    LP
    kernel
    SVM
    凸优化和对偶
    语音识别 -- 概述
  • 原文地址:https://www.cnblogs.com/DWdan/p/5094570.html
Copyright © 2011-2022 走看看