Day06-Object-COC特有语法

1. 内存管理概述

1.内存管理
内存的作用:存储数据
1). 如何将数据存储到内存之中
    声明1个变量, 然后将数据存储进去
2). 当数据不再被使用的时候, 占用的内存空间如何被释放
2.内存中的五大区域
栈: 局部变量, 当局部变量的作用域被执行完毕之后, 这个局部变量就会被系统立即回收
堆:OC对象, 使用C函数申请的空间
BSS段: 未初始化的全局变量, 静态变量, 一旦初始化就回收, 并转存到数据段之中
数据段: 已经初始化的全局变量, 静态变量, 直到程序结束的时候才会被回收
代码度: 代码, 程序结束的时候, 系统会自动回收存储在代码段中的数据
栈,BSS段, 数据段, 代码段存储在它们中的数据的回收, 是由系统自动完成的, 不需要我们干预
3. 分配在堆区中OC对象,是肯定需要被回收的
    iPhone 内存机制
    40M警告
    45M警告
    120M闪退
    存储在堆中的OC对象, 系统不会自动回收, 直到程序结束的时候才会被回收
4.内存管理的范围
只需要管理存储在堆中的OC对象的回收, 其他区域中的数据的回收是系统自动管理的
5.对象应该什么时候被回收
    当有人使用这个对象的时候,这个对象就千万不能回收
    只有在没有任何人使用这个对象的时候,才可以回收
6.引用计数器
    1).每1个对象都有1个属性, 叫做retainCount, 叫做引用计数器, 类型是unsigned long 占据8个字节
    引用计数器的作用: 用来记录当前这个对象有多少个人在使用它
    默认情况下,创建1个对象出来, 这个对象的引用计数器的默认值是1
    2).当多1个人使用这个对象的时候, 应该先让这个对象的引用计数器的值+1,代表这个对象多1个人使用
    3).当这个对象少1个人使用的时候,应该先让这个对象的引用计数器的值-1,代表这个对象少1个人使用
    4).当这个对象的引用计数器变为0的时候,代表这个对象无人使用, 这个时候系统就会自动回收这个对象
7.如何操作引用计数器
    1).为对象发送1条retain消息, 对象的引用计数器就会加1, 当多1个人使用对象的时候才发
    2). 为对象发送1条release消息, 对象的引用计数器就会减1, 当少1个人使用对象的时候才发
    3).为对象发送1条retainCount消息,就可以去到对象的引用计数器的值
    就这样++ -- 当对象的引用计数器变为0的时候, 对象就会被系统立即回收
    在对象被回收的时候,会自动调用对象的dealloc方法
8. 内存管理的分类
    MRC: Manual Reference Counting 手动引用计数, 手动内存管理
    当多1个人使用对象的时候, 要求程序员手动的发送retain消息, 少1个人使用的时候程序员手动的发送release消息
    2011年之前, IOS5之前
    ARC: Automatic Reference Counting 自动引用计数, 自动内存管理.系统自动的在合适的地方发送retain release消息
9. iOS5开始, Xcode4.2开始支持ARC
Xcode7 默认支持ARC开发
默认使用的开发方式就是ARC的模式
关闭ARC开启MRC
10. 当对象的引用计数器变为0的时候, 系统会自动回收对象
在系统回收对象的时候, 会自动的调用对象的dealloc方法
重写dealloc方法的规范:
必须要调用父类的dealloc方法, 并且要放在最后一句代码
11. 测试引用计数器
    1). 新创建1个对象, 这个对象的引用计数器的默认值是1   
    2).当对象的引用计数器变为0的时候,对象就会被系统立即回收, 并自动调用dealloc方法
    3).为对象发送retain消息, 对象的引用计数器就会+1
12. 为对象发送release消息, 并不是回收对象, 而是让对象的引用计数器-1;
当对象的引用计数器的值变为0的时候, 对象才会被系统立即回收

2. 内存管理的原则

1.内存管理的重点
    1). 什么时候为对象发送retain消息
    当多1个人使用这个对象的时候, 应该先为这个对象发送retain消息
    2). 什么时候为对象发送release消息
    当少1个人使用这个对象的时候, 应该为这个对象发送1条release消息
2. 在ARC机制下, retain release dealloc 这些方法无法使用的
3. 内存管理的原则
    1). 有对象的创建就要匹配1个release
    2).retain的次数和release的次数要匹配
    3).谁用谁retain, 谁不用谁release
    谁负责retain, 谁就负责release
    4).只有在多1个人用的时候才retain, 少1个人使用的时候才release
    有始有终,有加就有减, 有retain就应该匹配1个release, 一定要平衡

4.野指针与僵尸对象

1. 野指针
    C语言中的野指针: 定义1个指针变量, 没有初始化,这个指针变量的值是1个垃圾值, 指向1块随机的空间, 这个指针就叫做野指针
    OC中的野指针: 指针指向的对象已经被回收了, 这样的指针就叫做野指针
2. 对象的回收的本质:
    内存回收的本质:
    申请1个变量, 实际上就是想系统申请指定字节数的空间, 这些空间系统就不会再分配给别人了
    当变量被回收的时候, 代表变量占用的字节空间从此以后系统可以分配给别人使用了
    但是字节空间中存储的数据还在
    回收对象:
    所谓的对象的回收, 指的是对象占用的空间可以分配给别人.当这个对象占用的空间没有分配给别之前, 其实对象数据还在
3. 僵尸对象
    1个已经被释放的对象, 但是这个对象所占用的空间还没有分配给别人, 这样的对象叫做僵尸对象
    我们通过野指针去访问僵尸对象的时候, 有可能没问题也有可能有问题
    当僵尸对象占用的空间还没有分配给别人的时候,这是可以的
    当僵尸对象占用的空间分配给了别人使用的时候,就不可以了
4. 我们认为只要对象成为了僵尸对象, 无论如何, 都不允许访问了
    就希望如果访问的是僵尸对象,无论如何报错
    僵尸对象的实时检查机制, 可以将这个机制打开, 打开后,只要访问的是僵尸对象, 无论空间是否分配, 就会报错
5. 为什么不默认打开僵尸对象监测.
    一旦打开僵尸对象监测, 那么在每访问1个对象的时候, 都会先检查这个对象是否为1个僵尸对象
    这样是极其消耗性能的
6. 使用野指针访问僵尸对象会报错, 如何避免僵尸对象错误
    当1个指针成为野指针以后, 如何避免僵尸对象的错误
    当1个指针成为野指针以后,将这个指针的值设置为nil
    当1个指针的值为nil, 通过这个指针去调用对象的方法(包括使用点语法)的时候, 不会报错, 只是没有任何反应, 但是如果通过直接访问属性就会报错
7. 无法复活1个僵尸对象

5. 单个对象的内存管理

1.内存泄漏
    指的是1个对象没有被及时的回收, 在该回收的时候而没有被回收, 一直驻留在内存中,直到程序结束的时候才回收
2. 单个对象的内存泄漏的情况
    1).有对象的创建, 而没有对应的release
    2).retain的次数和release的次数不匹配
    3).在不适当的时候,为指针赋值为nil
    4).在方法中传入的对象进行不适当的retain
3.如何保证单个对象可以回收
    1).有对象的创建, 就必须要匹配1个release
    2).retain次数和release次数一定要匹配
    3).只有在指针为野指针的时候才赋值为nil

6. 多个对象的内存管理

1. 当属性是1个OC对象的时候, setter方法的写法
    将传进来的对象赋值给当前对象的属性, 代表传入的对象多了1个人使用, 所以我们应该先为这个传入的对象发送1条retain消息
    当当前对象销毁的时候, 代表属性指向的对象少1个人使用, 就应该在dealloc中release
    代码写法:
        -(void)setCar:(Car *)car
        {
            _car = [car retain];
        }
        -(void)dealloc
        {
            [_car release]
            [super dealloc]
        }
2. 当属性是1个OC对象的时候, setter方法照着上面那样写, 其实还是有问题的
    当为对象的这个属性多次赋值的时候, 就会发生内存泄漏
    发生泄漏的原因:当为属性赋值的时候, 代表旧对象少1个人使用, 新对象多1个人使用
    应该release旧的, retain新的
        -(void)setCar:(Car *)car
        {
            [_car release];
            _car = [car retain]
        }

8. @property参数

1. 在MRC的开发模式下, 1个类的属性如果是1个oc对象类型的, 那么这个属性的setter方法就应该按照下面的格式写
    -(void)setCar:(Car *)car
    {
        if(_car != car)
        {
            [_car release];
            _car = [car retain];
        }
    }
    还要重写dealloc方法
        -(void)dealloc
        {
            [_car release];
            {supper delloc];
        }
    如果属性的类型不是OC对象类型的, 不需要像上面那样写, 还是像之前那样写就ok了
2. @property
    1). 作用
        a. 自动生成私有属性
        b.自动生成这个属性的getter setter方法的声明
        c.自动生成这个属性的getter setter方法的实现
        生成的setter方法的实现中,无论是什么类型的, 都是直接赋值的
3. @property参数
    1). @property可以带参数的
    @property(参数1, 参数2, 参数3.....)数据类型 名称;
    2). 介绍一下@property的四组参数
    a.与多线程相关的两个参数
    atomic nonatomic
    b.与生成的setter方法的实现相关的参数
    assign retain
    c.与生成只读, 读写相关的参数
    readonly readwrite
    d. 是与生成的getter setter方法的名字相关的参数
    getter setter
4.介绍与多线程相关的参数
    atomic :默认值, 如果写atomic 这个时候生成的setter方法的代码就会被加上一把线程安全锁
    特点:安全  效率低下
    nonatomic:如果写nonatomic这个时候生成的setter方法的代码就不会加线程安全锁
    特点:不安全, 但是效率高
    建议:要效率, 选择使用nonatomic
5. 与生成的setter方法的实现相关的参数
    assign 默认值, 生成的setter方法的实现就是直接赋值
    retain:生成的setter方法的实现就是标准的MRC内存管理代码
    也就是, 先判断旧对象是否为同1个对象, 如果不是release旧的, retain新的
    当属性的类型是OC对象类型的时候, 那么就使用retain
    当属性的类型是非OC对象的时候, 使用assign
    千万注意:
    retain参数.只是生成标准的setter方法为标准的MRC内存管理代码, 不会自动的在dealloc中生成release的代码
    徐讴一, 我们还要自己手动的在dealloc中release
6.与生成只读, 读写的封装
readwrite:默认值, 代表同时生成getter setter
readonly:只会生成getter 不会生成setter
7. 生成getter setter方法名称相关的参数
    默认情况下, @property生成的getter setter 方法的名字都是标准的名字, 其实我们可以通过参数来指定@property生成的方法的名字
    getter = getter方法名字 ,用来指定@property生成的getter方法的名字
    setter = setter方法的名字, 用来指定@property生成的setter方法的名字, 注意setter方法是带参数的, 所以要加1个冒号
    如果使用getter setter修改了生成的方法的名字
    在使用点语法的时候, 编译器会转换为调用修改后的名字的代码
    修改生成的getter setter方法的名字, 因为默认情况下生成的方法的名字已经是最标准的名字了
    所以一般情况下不要修改去修改
    1). 无论什么情况都不要改setter方法的名字, 因为默认情况下生成的名字就已经是最标准的了
    2).什么时候修改getter方法的名字, 当属性的类型是1个BOOL类型的时候, 就修改这个getter的名字以is开头, 提高代码的阅读性

    与多线程相关的参数:用nonatomic
    与生成的setter方法实现相关的参数
    属性的类型是OC对象的时候, 使用retain
    属性的类型是非OC对象的时候, 使用assign
    只读, 读写
    如果你希望生成的封装是只读封装, 那么就使用readonly
    如果希望读写封装readwrite
    1).无论什么情况都不要改setter方法的名字, 因为默认情况下生成的名字就已经是最标准的了
    2).什么时候修改getter方法的名字, 当属性的类型是1个BOOL类型的时候, 就修改这个getter的名字以is开头,以提高代码的阅读性
    使用参数注意
    同1组参数只能使用1个
    getter setter可以同时使用
    参数的顺序可以随意

9. @class

1.当两个类相互包含的时候, 当Person.h中包含Book.h而Book.h中又包含Person.h, 这个时候,就会出现循环引用的问题, 就会造成无限递归的问题, 而导致无法编译通过
2.解决方案:
其中一边不要使用#import引入对方的头文件
而是使用@class类名, 来标注这个1个类, 这样子就可以在不引入对方头文件的情况下, 告诉编译器这是1个类
在.m文件中再#import对方的头文件, 就可以使用了
3.@class与#import的区别
    1).#import是将指定的文件的内容拷贝到写指令的地方
    2).@class并不会拷贝任何内容, 只是告诉编译器,这是1个类, 这样编译器在编译的时候才可以知道这是1个类

10. 循环retain

1.当两对象相互引用的时候
A对象的属性是B对象, B对象的属性是A对象
这个时候, 如果两边都使用retain, 那么就会发生内存泄漏
2.解决方案:1端使用retain, 另外1端使用assign使用assign的那1端在dealloc中不再需要release了
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ava实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),可运行高分资源 Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现
C语言是一种广泛使用的编程语言,它具有高效、灵活、可移植性强等特点,被广泛应用于操作系统、嵌入式系统、数据库、编译器等领域的开发。C语言的基本语法包括变量、数据类型、运算符、控制结构(如if语句、循环语句等)、函数、指针等。下面详细介绍C语言的基本概念和语法。 1. 变量和数据类型 在C语言中,变量用于存储数据,数据类型用于定义变量的类型和范围。C语言支持多种数据类型,包括基本数据类型(如int、float、char等)和复合数据类型(如结构体、联合等)。 2. 运算符 C语言中常用的运算符包括算术运算符(如+、、、/等)、关系运算符(如==、!=、、=、<、<=等)、逻辑运算符(如&&、||、!等)。此外,还有位运算符(如&、|、^等)和指针运算符(如、等)。 3. 控制结构 C语言中常用的控制结构包括if语句、循环语句(如for、while等)和switch语句。通过这些控制结构,可以实现程序的分支、循环和多路选择等功能。 4. 函数 函数是C语言中用于封装代码的单元,可以实现代码的复用和模块化。C语言中定义函数使用关键字“void”或返回值类型(如int、float等),并通过“{”和“}”括起来的代码块来实现函数的功能。 5. 指针 指针是C语言中用于存储变量地址的变量。通过指针,可以实现对内存的间接访问和修改。C语言中定义指针使用星号()符号,指向数组、字符串和结构体等数据结构时,还需要注意数组名和字符串常量的特殊性质。 6. 数组和字符串 数组是C语言中用于存储同类型数据的结构,可以通过索引访问和修改数组中的元素。字符串是C语言中用于存储文本数据的特殊类型,通常以字符串常量的形式出现,用双引号("...")括起来,末尾自动添加'\0'字符。 7. 结构体和联合 结构体和联合是C语言中用于存储不同类型数据的复合数据类型。结构体由多个成员组成,每个成员可以是不同的数据类型;联合由多个变量组成,它们共用同一块内存空间。通过结构体和联合,可以实现数据的封装和抽象。 8. 文件操作 C语言中通过文件操作函数(如fopen、fclose、fread、fwrite等)实现对文件的读写操作。文件操作函数通常返回文件指针,用于表示打开的文件。通过文件指针,可以进行文件的定位、读写等操作。 总之,C语言是一种功能强大、灵活高效的编程语言,广泛应用于各种领域。掌握C语言的基本语法和数据结构,可以为编程学习和实践打下坚实的基础。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值