一、对象在内存中的存储细节
1.类创建对象,每个对象在内存中都占据一定的存储空间,有一份属于自己的单独的成员变量,所有的对象公用类的成员方法,方法在整个内存中只有一份。类本身在内存中占据一份存储空间,类的方法存储与此。
*堆栈的概念:栈一般由系统自动分配释放存放的是函数的参数值,局部变量等可以直接引用的数据,操作方式类似于数据结构中的栈;堆一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收,分配方式类似于链表。
string str1=“111”;string str2="111";
这里string其实是一个类,但是str1和str2并不是对象,而是指向对象的引用,符串“111”才是对象。另外string是一个指针,所以str1和str2其实都是指针变量。当创建str1变量后,编译器内部会搜索有没有存放“111”这个字面值的地址空间。如果没有就开辟一个存放“111”。然后str1指向这个空间的地址。在创建str2之后,编译器搜索发现有存放“111”这个字面值的地址空间。所以直接指向这个空间的地址。不用开辟新的。
A a = new A();
这里在堆中new了一个空间给a。但是注意,a本身在栈中。alloc,copy是类似的。
2.每个对象都有一个隐藏指针isa,指向当前对象所属的类。当对象调用某个方法时,对象会顺着isa指针找到存储于类中的方法,然后执行。
注意,当一个类创建多个对象时,不同对象在内存中分配的是不同的存储地址,各成员属性地址也不相同。
二、引用计数器
1.每个OC对象都有自己的引用计数器(int类型,4字节),表示对象被引用次数。
使用alloc/new/copy创建一个新的对象时,新对象的引用计数器为1,当引用计数器为0时,对象占用的内存会被系统回收。
2.这里介绍四个方法:
1>retainCount 该方法返回当前计数器的值
2>retain 计数器加一,该方法返回对象本身
3>release 计数器减一,该方法没有返回值
4>dealloc 在对象计数器为0,它将被销毁,其占用的内存会被系统回收,此时系统会自动向对象发送该方法
注意:一般会重写dealloc方法,在这里释放相关资源。但重写dealloc方法时一定要调用[super dealloc]方法,并置于代码块的最后。不要使用dealloc方法来管理稀缺资源,比如文件,网络链接等。因为由于bug或者程序意外退出,dealloc方法不能保证一定会被调用。
3.当一个对象已经被释放,而某个指针依旧指向该对象,此时你使用这个指针可能会产生一个比较常见的错误:
EXC_BAD_ACCESS---坏访问错误(内存已被回收,不可用),也叫野指针错误。
(野指针:只想僵尸对象----不可用内存的指针)
解决方法就是在对象内存被回收之后,清空这个指针,令其等于nil
三、内存管理
1.内存管理的目的是:
1>不要释放或者覆盖还在使用的内存,这会引起程序崩溃;
2>释放不再使用的内存,防止内存泄露。iOS程序的内存资源是宝贵的。
注意:管理范围只对任何继承NSObject的对象,对其他的基本数据类型无效。
2.内存管理法则:
1>alloc、