引用计数器
在ObjC中内存的管理是依赖对象引用计数器来进行的,ObjC中内存的管理在ObjC中每个对象内部都有一个与之对应的整数(retainCount),叫引用计数器”,当一个对象在创建之后它的引用计数器为1,当调用这个对象的alloc、retain、new、copy方法之后引用计数器自动在原来的基础上加1(ObjC中调用一个对象的方法就是给这个对象发送一个消息),当调用这个对象的release方法之后它的引用计数器减1,如果一个对象的引用计数器为0,则系统会自动调用这个对象的dealloc方法来销毁这个对象。
自动释放池
在ObjC中也有一种内存自动释放的机制叫做自动引用计数(或“自动释放池”),与C#、Java不同的是,这只是一种半自动的机制,有些操作还是需要我们手动设置的。自动内存释放使用@autoreleasepool关键字声明一个代码块,如果一个对象在初始化时调用了autorelase方法,那么当代码块执行完之后,在块中调用过autorelease方法的对象都会自动调用一次release方法。
-
autorelease方法不会改变对象的引用计数器,只是将这个对象放到自动释放池中;
-
自动释放池实质是当自动释放池销毁后调用对象的release方法,不一定就能销毁对象(例如如果一个对象的引用计数器>1则此时就无法销毁);
常量 和 对象?堆 ?栈?
-
常量:会被放入栈中,他们依次紧密排列,在内存中占有一块连续的内存空间,遵循先进后出的原则。
-
对象:会被放到堆中,当给对象分配内存空间时,会随机的从内存当中开辟空间,对象与对象之间可能会留有不确定大小的空白空间,因此会产生很多内存碎片,需要我们管理。
-
栈内存与堆内存从性能上比较,栈内存要优于堆内存,这是因为栈遵循先进后出的原则,因此当数据量过大时,存入栈会明显的降低性能。因此,我们会把大量的数据存入堆中,然后栈中存放堆的地址,当需要调用数据时,就可以快速的通过栈内的地址找到堆中的数据。
内存管理修饰符
- ARC
strong :强引用,ARC中使用,与MRC中retain类似,使用之后,计数器+1。
copy :表示拷贝,setter方法将传入对象复制一份,需要完全一份新的变量时。
assign :用于基本数据类型, 相当于MRC中的 assign。
weak : 用于OC对象, 相当于MRC中的 assign。
- MRC
retain :表示持有特性,setter方法将传入参数先保留,再赋值,传入参数的retaincount会+1。
- 其他
readwrite : 可读可写特性,需要生成getter方法和setter方法时使用。
readonly : 只读特性,只会生成getter方法 不会生成setter方法,不希望属性在类外改变。
nonatomic :非原子操作,不加同步,多线程访问可提高性能,但是线程不安全的。
atomic :原子操作,同步的,表示多线程安全,与nonatomic相反。
- strong 和 copy 的区别?
#import "ViewController.h"
@interface ViewController ()
@property (nonatomic, strong) NSString *mStrongString;
@property (nonatomic, copy) NSString *mCopyString;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// mStrongString 和 mCopyString 的指针指向了mStr。
// 当mStr 的值改变的时候,mStrongString 会随之改变。
// mCopyString 的值不会随着改变。
NSMutableString *mStr = [NSMutableString stringWithString:@"hello"];
self.mStrongString = mStr;
self.mCopyString = mStr;
[mStr appendString:@"word"];
NSLog(@"theStrongName = %@, theCopyName = %@",
self.mStrongString, self.mCopyString);
}
输出结果:2016-12-21 13:52:35.678 L[30705:2526456]
theStrongName = helloword, theCopyName = hello
- strong 和 weak 的区别?
这篇文章可以很好的理解~~原理也很清晰