IOS基础入门OC语言Xcode Day06笔记:类在内存中的存储

1、内存中的五大区域
栈:存储局部变量
堆:程序员手动申请的字节空间 malloc calloc realloc函数
BSS字段:存储未被初始化的全局变量、静态变量
数据段(常量区):存储已被初始化的全局变量、静态变量、常量数据
代码段:存储代码,存储程序的代码

2、类加载
1)在创建对象的时候,肯定是需要访问类的
2)声明一个类的指针变量也会访问类的
在程序运行期间,当某个类第一次被访问的时候,会将这个类存储到内存中的代码段区域,这个过程叫做类加载。
只有类在第一次被访问的时候,才会做类加载。
一旦类被加载到代码段以后,直到程序结束的时候才会被释放

3、对象在内存中究竟是如何存储的
假设下面这个写在函数之中

Person *p1 = [Person new];
1)Person *p1;会在栈内存中申请一块空间,在栈内存中声明一个Person类型的指针变量p1,
p1是一个指针变量,那么只能存储地址。

2)[Person new];真正在内存中创建对象的其实是这句代码。
new做的事情:
	a、在堆内存中申请一块合适大小的空间;
	b、在这个空间中根据类的模板创建对象;
		类模板中定义了什么属性,就把这些属性依次声明在对象之中,
		对象中还有另外一个属性,叫做isa,是一个指针,指向对象所属的类在代码段中的地址。
	c、初始化对象的属性
		如果属性的类型是基本数据类型,那么就赋值为0;
		如果属性的类型是C语音的指针类型,那么就赋值为NULL;
		如果属性的类型是OC的类指针类型,那么就赋值为nil;
	d、返回对象的地址
	
3)注意
	a、对象中只有属性,而没有方法,自己类的属性外加一个isa指针指向代码段中的类
	b、如何访问对象的属性
		指针名->属性名;
		根据指针,找到指针指向的对象,再找到对象中的属性来访问
	c、如何调用方法
		[指针名 方法名];
		先根据指针名找到对象,对象发现要调用方法,再根据对象的isa指针找到类,然后调用类里的方法

4、为什么不把方法存储在对象之中?
因为每一个对象的方法的代码实现都是一模一样的,没有必要为每一个对象都保存一个方法,这样的话就太浪费空间了,
既然都一样,那么就只保持一份。

5、对象的属性的默认值
如果我们创建一个对象,没有为对象的属性赋值,那么这个对象的属性是有值的。
如果属性的类型是基本数据类型,那么默认值值为0;
如果属性的类型是C语音的指针类型,那么默认值为NULL;
如果属性的类型是OC的类指针类型,那么默认值为nil;

1)NULL
	可以作为指针变量的值,如果一个指针变量的值是NULL值代表,代表这个指针不指向内存中的任何一块空间,
	NULL其实等价于0;NULL其实是一个宏,就是0.
2)nil
	只能作为指针变量的值,代表这个指针变量不指向内存中的任何一块空间,
	nil其实也等价于0,也是一个宏,就是0;
	所以,NULL和nil其实是一样的;
3)使用建议
	虽然使用NULL的地方可以是nil,使用nil的地方可以使用NULL,但是不建议大家去随便使用
		C指针用NULL
			int *p1 = NULL;   //p1指针不指向内存中的任何一块空间;
		OC的类指针用nil
			Person *p1 = nil;   //p1指针不指向任何对象;
4)如果一个类指针的值为nil,代表这个指针不指向任何对象
	Person *p1 = nil;
	那么这个时候,如果通过p1指针去访问p1指向的对象的属性,这个时候会运行报错;
	那么这个时候,如果通过p1指针去调用对象的方法,运行不会报错,但是方法不会执行,没有任何反应		

6、多个指针指向同一个对象
1)同类型的指针变量之间是可以相互赋值的
Person *p1 = [Person new];
Person *p2 = p1; //这是完全没有问题的,p1和p2的类型都是Person指针类型的;
代表将p1的值赋值给p2,而p1的值是对象的地址,所以就把对象的地址赋值给了p2,所以p1和p2指向了同一个对象;
无论通过p1还是p2去修改对象,修改的都是同一个对象;
2)目前为止,只要看到new,就说明新创建了一个对象。

7、分组导航标记
1)#pragma mark 分组名
就会在导航条对应的位置显示一个标题
2)#pragma mark -
就会在导航条对应的位置显示一条水平分割线
3)#pragma mark - 分组名
就会在导航条对应的位置现产生一条水平分割线,再显示标题

猜你喜欢

转载自blog.csdn.net/wenyu_Saitama/article/details/106994240