1.內(nèi)存存儲區(qū)域
C、C++里面。棧區(qū):存儲臨時變量和對象。堆區(qū)域:存儲動態(tài)分配對象。靜態(tài)變量存儲區(qū):存儲靜態(tài)變量和常量對象。
OC里面的內(nèi)存存儲區(qū)域跟C、C++一樣。
2.為什么要進(jìn)行內(nèi)存管理
寫過C、C++程序的都知道,內(nèi)存管理永遠(yuǎn)是C++程序的一大痛點(diǎn),項目當(dāng)中崩潰全部來自于內(nèi)存相關(guān)的操作,尤其是指針操作和內(nèi)存操作,稍不注意就會產(chǎn)生內(nèi)存訪問違規(guī)造成程序崩潰。那么如何進(jìn)行內(nèi)存管理呢,個人認(rèn)為有以下幾點(diǎn)原則:盡量用系統(tǒng)提供給我們的封裝對象,不要用原生的,比如用string而不要用char*,用string能避免項目中大部分的字符串違規(guī)操作;能在棧上分配就不在堆上分配,利用棧的自動釋放功能幫我們釋放;對于復(fù)雜的內(nèi)存操作比如多個類或者多個線程引用同一塊內(nèi)存,那就給這塊內(nèi)存加引用計數(shù);內(nèi)存操作一定要判空操作。
我們知道OC中的所有對象都是動態(tài)分配的,那么OC中是如何管理這些對象的呢?答案是利用引用計數(shù)來管理。
3.OC中對象內(nèi)存管理
OC中通過引用計數(shù)來管理對象的生命周期。
- (instancetype)retain OBJC_ARC_UNAVAILABLE; //引用加1
- (oneway void)release OBJC_ARC_UNAVAILABLE; //引用減1
- (instancetype)autorelease OBJC_ARC_UNAVAILABLE; //自動釋放對象
- (NSUInteger)retainCount OBJC_ARC_UNAVAILABLE; //返回當(dāng)前的引用技術(shù)
當(dāng)對象B擁有對象A時,設(shè)置對象A時,最好掉用Retain提升引用計數(shù),在dealloc方法里面減少引用技術(shù)。
注意下面代碼的中(void) setA : (A*) pAIn實(shí)現(xiàn)
-(void) setA : (A*) pAIn
{
[pAIn retain];
[pA release];
pA = pAIn;
}
先保留PAIn,再釋放PA,然后賦值,這種寫法能有效地避免PAIn和PA指向同一對象這種情況,強(qiáng)烈建議一定要這樣寫。
代碼如下:
@interface A : NSObject- (void) disInfo;@end@implementation A- (void) disInfo{ NSLog(@"I'm A haha!");}@end@interface B : NSObject{@PRivate A* pA;}-(void) setA : (A*) pAIn;-(void) disA;@end@implementation B- (void)dealloc{ [pA release]; [super dealloc];}-(void) setA : (A*) pAIn{ [pAIn retain]; [pA release]; pA = pAIn;}-(void) disA{ [pA disInfo];}@endint main(int argc, const char * argv[]) { A* pA = [A new]; B* pB = [B new]; [pB setA:pA]; [pB disA]; [pB release]; [pA release]; return 0;}上面的例子中我們需要手動地掉用retain和release方法,也就是說我們需要知道何時要retain,何時需要release,很顯然在業(yè)務(wù)邏輯很復(fù)雜的情況下需要追蹤引用計數(shù)造成的問題需要花費(fèi)比較多的時間。那么,如何讓對象自動retain和release呢?寫過Windows Com程序的人知道CComPtr這個智能指針類,OC又是如何做的呢?下面揭曉。
4.OC中自動釋放內(nèi)存
Cocoa中的自動釋放池@autoreleasepool和NSAutoreleasepool配合對象的autorelease方法來實(shí)現(xiàn)自動釋放內(nèi)存。
1)利用autoreleasepool和autorelease。代碼如下:
@autoreleasepool { A* pA = [A new]; [pA autorelease]; B* pB = [B new]; [pB autorelease]; [pB setA:pA]; [pB disA]; }上面的代碼跟3中的代碼相比優(yōu)勢在:在pA和pB創(chuàng)建完成之后直接調(diào)用autorelease方法將對象加入自動釋放吃,代碼緊湊,后面再也不用擔(dān)心在什么時候release了。
2)利用NSAutoreleasePool和autorelease。代碼如下:
NSAutoreleasePool* pool = [NSAutoreleasePool new]; A* pA = [A new]; [pA autorelease]; B* pB = [B new]; [pB autorelease]; [pB setA:pA]; [pB disA]; [pool release];
代碼跟跟利用關(guān)鍵字@autoreleasepool的代碼差不多。
那么面對著兩種方式,我們應(yīng)該選擇哪種呢?個人認(rèn)為有一下幾種原則:
1)對于對象操作緊湊的代碼用@autoreleasepool,因為他的效率比NSAutoreleasePool高
2)對象A擁有一些例對象并且這些對象保留在NSArray等數(shù)組中,用 NSAutoreleasePool,因為只需要在A的dealloc對象當(dāng)中調(diào)用NSAutoreleasePool的release方法,保存在NSArray的對象就會自動釋放,很顯然@autoreleasepool不具備這樣的能力。
新聞熱點(diǎn)
疑難解答