Objective-C教程之对象在内存中的存储(05)

本文探讨Objective-C中对象在内存中的存储方式,包括内存五大区域和类加载。通过Xcode设置断点调试,验证对象创建过程,展示如何查看对象的内存地址、属性值以及对象与类模板的关系。在调试过程中,观察对象指针、属性初始化状态,强调方法存储于类模板而非对象本身,以节省空间。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

对象在内存中的存储

知识点:内存中的五大区域;类加载;对象在内存中是如何存储的。

#import <Foundation/Foundation.h>

@interface Person : NSObject
{
    @public
    NSString *_name;
    int _age;
    int *p1;
}
- (void)selfInfo;
@end // Person

@implementation Person
- (void)selfInfo
{
    NSLog(@"大家好,我是%@,今年%d岁啦~", _name, _age);
}
@end // person

int main(int argc, const char * argv[]) {
    // 创建p1对象时,进行类加载;创建p2对象时不会
    Person *p1 = [Person new];
    //Person *p2 = [Person new];
    
    p1->_name = @"Emun";
    p1->_age = 20;
    
    [p1 selfInfo];
    
    NSLog(@"验证p1的值是否为地址:p1 = %p", p1);
    
    return 0;
}
/*
 对象在内存中的存储
 1.内存中的五大区域
    栈:存储局部变量
    堆:程序员手动申请的字节空间;malloc calloc realloc函数
    BSS段:存储未被初始化的全局变量,静态变量
    数据段(常量区):存储已被初始化的全局变量,静态变量,常量数据
    代码段:存储代码
 2.类加载
    1)在创建对象的时候,是需要访问类的
    2)声明一个类的指针变量画也会访问类
    在程序运行期间,当某个类第一次被访问到的时候,会将这个类存储到内存中的代码段区域,这个过程叫做类加载。
    只有类在第一次被访问的时候,才会做类加载;一旦类被加载到代码段以后,直到程序结束才会被释放。
 3.对象在内存中是如何存储的
    首先在main函数中执行--Person *p1 = [Person new];
    1)Person *p1  会在栈内存中申请一块空间,意思是在栈内存中声明一个Person类型的指针变量p1。(p1是一个指针变量,只能存储地址)
    2)[Person new]  真正在内存中创建对象的是这串代码,new是一个方法,做的事情有:
                    a.在堆内存中申请一块合适大小的空间
                    b.在这个空间中根据类的模板创建对象(将类模板中定义的属性依次声明在对象之中)
                      对象中还会有另外一个属性,叫做 isa ,是一个指针,指向类模板在代码段中的地址
                    c.初始化类的属性
                      如果属性的类型是基本数据类型,那么就赋值为0
                      如果属性的类型是C语言的指针类型,那么就赋值为NULL
                      如果属性的类型是OC的类指针类型,那么就赋值为nil
                    d.返回对象的地址给p1指针
    3)注意:
        a.对象中只有属性(根据类模板声明的属性外加一个isa属性),而没有方法
        b.访问对象的属性  指针名(对象名)->属性名  例:p1->_name = @"Emun";
          过程:其实是根据p1指针中存储的地址找到对象,再找到对象中的属性来访问
        c.调用方法  [指针名 方法名]; 例:[p1 selfInfo];
          过程:先根据指针名找到对象,再根据对象中的 isa 属性找到类,再从类中调用方法
 */

调试并验证

首先来看一下控制台输出,验证p1存储的是否是个十六进制地址
控制台输出
Xcode添加断点调试验证对象创建过程:
1.首先,找到创建对象的那一行代码,点击左侧对应的行数,有了蓝色指向背景即在此处创建了断点(不小心点错了行数或者想取消该断点的话,直接鼠标左键按住蓝色指向标志向外拖动即可)。
添加断点
2.点击左上角三角运行按钮或者快捷键Command+R运行;代码在断点处停止,点击选中p1,可出现一个小提示框,由于此行代码还未运行,p1的值为空,点击小眼睛图标也可查看p1的各种信息,其中TypePerson *Value为0(验证了p1是Person类型的指针变量)
断点调试p1的详细信息
3.点击下方控制台的下一步,让程序往下走
下一步
4.此时再查看p1的详细信息,发现Value值为一个十六进制地址,同时可以对比最终控制台打印的p1值的结果,二者相等。
p1对象的信息
5.点击左侧三角形展开查看更多信息,再点击NSObject左侧的小三角展开,可以看到一个isa属性,点击小眼睛查看详细信息,发现其Value值也为一个十六进制地址,其指向类模板的位置;
同时,我们还能看到根据类模板创建的属性,且已被初始化:
_age属性的类型是基本数据类型,被赋值为0
p1属性的类型是C语言的指针类型,被赋值为NULL
_name属性的类型是OC的类指针类型,被赋值为nil
还需注意p1对象中并没有存储方法,而是通过isa去访问类模板的的方法,主要目的是为了节省空间。
展开更多信息
查看更多信息
6.继续点击两次下一步,执行完对象属性的赋值,查看对象p1的信息,发现属性已被赋值。最后点击下一步左边的按钮,将程序全部执行完即可
再次查看
执行程序
结束啦,别忘了将断点拖动移除喔,不然程序下次依然会在断点处停止~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值