objective-c 对象所占内存总是分配在“堆空间”,并且堆内存是由你释放的,即release。一般由程序员分配释放,若程序员不释放,则可能会引起内存泄漏。注 堆和数据结构中的堆栈不一样,其类似于链表
栈区(stack)
由编译器自动分配释放,存放函数的参数值,局部变量等值。其操作方式类似于数据结构中的栈。
栈是一个用来存储局部和临时变量的存储空间。在现代操作系统中,一个线程会分配一个栈. 当一个函数被调用,一个stack frame(栈帧)就会被压到stack里。里面包含这个函数涉及的参数,局部变量,返回地址等相关信息。当函数返回后,这个栈帧就会被销毁。而这一切都是自动的,由系统帮我们进行分配与销毁。对于程序员来说,我们无须自己调度。
堆区(heap)
一般由程序员分配释放,若程序员不释放,则可能会引起内存泄漏。注 堆和数据结构中的堆栈不一样,其类似于链表。
堆从本质上来说,程序中所有的一切都在内存中(有些东西是不在堆栈中的,但在这篇文章中我们不作讨论)。在堆上,我们可以任何时候分配内存空间以及释放销毁它。你必须显示的请求在堆上分配内存空间,如果你不使用垃圾回收机制,你必须显示的去释放它。这就是在你的函数调用前需要完成的事情。简单来说,就是malloc与free。
通常以这种方式创建对象
NSObject *obj = [[NSObject alloc] init];
系统会在栈上存储obj这个指针变量,它所指的对象在堆中。通过[NSObject alloc]系统会为其在堆中开辟一块内存空间,并为其生成NSObject所需内存结构布局。
优缺点
栈对象
优点:
- 高速,在栈上分配内存是非常快的。
- 简单,栈对象有自己的生命周期,你永远不可能发生内存泄露。因为他总是在超出他的作用域时被自动销毁了
缺点:
栈对象严格的定义了生命周期也是其主要的缺点,栈对象的生命周期不适于Objective-C的引用计数内存管理方法。
在objective-c中只支持一个类型对象:blocks。关于在block中的对象的生命周期问题。出现这问题的原因是,block是新的对象,当你使用block时候,如果你想对其保持引用,你需要对其进行copy操作,(从栈上copy到堆中,并返回一个指向他的指针),而不是对其进行retain操作
堆对象
优点:可以自己控制对象的生命周期。
缺点:需要程序员手动释放,容易造成内存泄漏。
assign 为什么不能修饰OC对象
对象的内存一般被分配到堆上,基本数据类型和oc数据类型的内存一般被分配在栈上。
如果用assign修饰对象,当对象被释放后,指针的地址还是存在的,也就是说指针并没有被置为nil,从而造成了野指针。因为对象是分配在堆上的,堆上的内存由程序员分配释放。而因为指针没有被置为nil,如果后续的内存分配中,刚好分配到了这块内存,就会造成崩溃。
而assign修饰基本数据类型或oc数据类型,因为基本数据类型是分配在栈上的,由系统分配和释放,所以不会造成野指针。