zoukankan      html  css  js  c++  java
  • OC之对象在内存的位置

    对象在内存中的存储

    1. 内存中的五大区域.

        栈: 存储局部变量.

        堆: 允许程序员手动在堆区申请指定的连续的字节数的空间来使用.

        BSS段: 存储未初始化的全局变量、静态变量.

        数据段(常量区):  存储已经初始化的全局变量、静态变量、常量数据.

        代码段:存储程序的代码.

    2. 类加载.

        1). 当创建对象的时候,肯定需要访问这个类.因为只有访问了类才知道类中有那些成员.

        2). 如果只是声明类指针的时候,也会访问这个类.以确定这个类型是否存在.

        当类第一次被访问的时候,会将类存储到代码段之中. 这个过程叫做类加载.

        将类的代码存储在代码之中.

        将类的代码以字符串的形式存储在代码段中.

        只有类第1次被访问的时候,才会有类加载.   

        一旦类被加载到代码区.直到程序结束的时候才会被回收.

    3.对象在内存中是如何存储的.

       1). 类的本质是:自定义的数据类型.

           HMPerson *p1 = [HMPerson new];

       2). HMPerson *p1;

           这句话,仅仅是声明了1个指针变量而已.这个指针变量的类型是HMPerson*.

           p1是1个局部的变量.所以p1指针变量是存储在栈区的.

           p1是1个指针变量,所以这个变量中只能存储地址.

           本质上来讲.p1是1个指针变量 不是1个对象.

        3).[HMPerson new];

           这句话,才是在真正的创建对象.

           new做的事情.

           a. 在堆内存中申请一块合适大小的空间.

           b. 在申请的这块空间中根据类的模板创建对象.

              类中有哪些属性.就把类的属性依次的挨个的一个不落的声明在这个对象中.

              对象中除了有类中定义的属性之外,还有1个属性叫做isa 这是1个指针.

              这个isa指针指向代码段中的类.

           c. 初始化对象的属性.为对象的属性赋默认值

              -> 如果属性的类型是基本数据类型.就赋值为0

              -> 如果属性的类型是C指针类型.就赋值为NULL

              -> 如果属性的类型是OC指针类型.就赋值为nil

           d. 返回这个对象在堆空间中的地址.

              将这个地址赋值给p1指针.

              p1指针指向了堆空间中的HMPerson对象.

        4). 注意

            a. 对象中只有类的属性+isa的指针. 没有方法.

               isa指针指向了代码段中的类.

            b. 如何访问对象的属性.

               通过指针就可以找到指针指向的对象.找到对象了,就可以找到对象的属性.

              p1->_name = @"jack";

            c. 如何调用对象的方法?

               [p1 sayHi];

               通过p1指针找到对象,发现是在调用方法.那么再根据对象的isa指针找到代码段中的类.

               再找到类中的对应的方法来执行.

            d. 为什么方法不保存在对象中.

               因为不管对象有多少个.方法的代码都是一样的.没有必要保存多份,只保存1份就可以了.

            e. 相同类的对象的isa指针的值一定都是一样的.

    4. 对象的属性的初始值.

        创建1个对象 如果没有为这个对象的属性赋值.那么这个对象的属性是有值的.

        属性的类型是基本数据类型:  0

                  OC指针:      nil

                  C指针:       NULL

             

    Nil

    1. C语言中学习的NULL.

        a). NULL是1个值. 是C语言中指针变量的值.

        b). 如果1个指针的值为NULL值,就代表这个指针不指向内存中的任何空间.

        c). NULL本质上是1个宏.

            define NULL ((void*)0)

            所以 NULL 和 0 等价.

    2. nil

        a). nil也是1个值. 它也是1个指针变量的值.

        b). nil的本质也是1个宏.

            #define __DARWIN_NULL ((void *)0)

            所以,nil和NULL完全是等价的.

    c). 所以,如果

    想要让1个指针不指向任何空间.

            可以为这个指针变量赋值为NULL nil 0

    3. 使用建议

        a). 如果希望C指针不指向任何空间.一般为其赋值为NULL

        b). 如果希望OC指针不指向任何空间,一般赋值nil

    4. 注意问题

        如果1个类指针的值为nil

        HMPerson *p1 = nil;

        代表p1指针不指向任何对象.

         1). 所以这个时候 通过p1去访问p1指向的对象的属性的时候,肯定的会报错.

            对象都没有 哪里来的属性呢?

        2). 这个时候, 通过这个指针去调用方法的时候,

            不会报错.也不会崩溃.

            只是没有任何反应的啦.

    分组导航标记

    1. 一种快速的方式查找文件中的代码.

        Xcode 提供了导航条可以快速查找.

    2. 分组导航标记.

        1). #pragma mark 标记名.

        2). #pragma mark -  就会产生1条分割线.

    3). #pragma mark - 标记名.  就会产生1条分割线.并取1个标记名.

    方法与函数

    1. 之前在C语言中叫做函数.

        void test();

        在OC类中定义的叫做方法.

        - (void)sayHi;

    2. 相同点:

        1). 都封装1段代码,都表示1个相对独立的功能.

        2). 函数/方法 如果不被调用,那么其中的代码是不会被执行.

    3. 不同点.

        1). 语法不同.

        2). 定义的位置不一样.

            a. 函数除了函数的内部和@interface的大括弧中不能定义.其他的地方都是可以定义的.

            b. 而方法的声明只能在@interface的大括弧的外面,实现只能在@implementation中.

            就算把函数写在类中,这个函数也不是属于这个类的.

        3). 归属感不同.

            a, 函数就像是1个没有家的孩子,每1个函数是孤立的.]

            b. 方法是属于类的.类就是方法的家.

        4). 调用形式不同.

            a. 函数直接调用.

            b. 方法必须要通过对象名来调用.

    不忘初心,方得始终
  • 相关阅读:
    Pycharm使用
    解决TortoiseGit下载代码每次要输入用户名、密码
    GitLab创建项目
    【编码格式错误】SyntaxError: Non-UTF-8 code starting with
    C 位段,位域
    跳跃表 -- 随机平衡原理
    PHP 中的新语法 new static 是个啥意思?
    位运算之——按位与(&)操作——(快速取模算法)
    Redis Scan迭代器遍历操作原理(一)
    Redis Scan迭代器遍历操作原理(二)
  • 原文地址:https://www.cnblogs.com/jialiangliang/p/6184997.html
Copyright © 2011-2022 走看看