iOS關(guān)于內(nèi)存管理

在OC中對象是存儲在堆中的,系統(tǒng)并不會自動釋放堆中的內(nèi)存,如果一個對象創(chuàng)建并使用后沒有得到及時釋放那么就會占用大量內(nèi)存。其他高級語言如C#、Java都是通過垃圾回收來(GC)解決這個問題的,但在OjbC中并沒有類似的垃圾回收機(jī)制,因此它的內(nèi)存管理就需要由開發(fā)人員手動維護(hù)。

引用計數(shù)器

在Xcode4.0之后,引入了ARC(Automatic Reference Counting)機(jī)制,程序編譯時Xcode可以自動給你的代碼添加內(nèi)存釋放代碼,如果編寫手動釋放代碼Xcode會報錯,因此在今天的內(nèi)容中如果你使用的是Xcode4.2之后的版本(相信現(xiàn)在大部分朋友用的版本都比這個要高),必須手動關(guān)閉ARC,這樣才有助于你理解ObjC的內(nèi)存回收機(jī)制。

Xcode關(guān)閉ARC:選中工程—>Build Settings-->輸入garbage找到Objective-C Automatic Reference Counting設(shè)置為No

在ObjC中內(nèi)存的管理是依賴對象引用計數(shù)器來進(jìn)行的:在ObjC中每個對象內(nèi)部都有一個與之對應(yīng)的整數(shù)(retainCount),叫“引用計數(shù)器”,當(dāng)一個對象在創(chuàng)建之后它的引用計數(shù)器為1,當(dāng)調(diào)用這個對象的alloc、retain、new、copy方法之后引用計數(shù)器自動在原來的基礎(chǔ)上加1(ObjC中調(diào)用一個對象的方法就是給這個對象發(fā)送一個消息),當(dāng)調(diào)用這個對象的release方法之后它的引用計數(shù)器減1,如果一個對象的引用計數(shù)器為0,則系統(tǒng)會自動調(diào)用這個對象的dealloc方法來銷毀這個對象。

代碼如下:

#import <Foundation/Foundation.h>
#import "Person.h"
void Test1(){
 Person *p=[[Person alloc]init]; //調(diào)用alloc,引用計數(shù)器+1 p.name=@"Kenshin"; p.age=28; 
NSLog(@"retainCount=%lu",[p retainCount]);
 //結(jié)果:
retainCount=1 [p release]; //結(jié)果:Invoke Person's dealloc method. 
//上面調(diào)用過release方法,p指向的對象就會被銷毀,但是此時變量p中還存放著Person對象的地址, 
//如果不設(shè)置p=nil,則p就是一個野指針,它指向的內(nèi)存已經(jīng)不屬于這個程序,因此是很危險的 p=nil; 
//如果不設(shè)置p=nil,此時如果再調(diào)用對象release會報錯,但是如果此時p已經(jīng)是空指針了, 
//則在ObjC中給空指針發(fā)送消息是不會報錯的 
[p release];
}

void Test2(){
 Person *p=[[Person alloc]init]; 
p.name=@"Kenshin";
 p.age=28;
 NSLog(@"retainCount=%lu",[p retainCount]); 
//結(jié)果:
retainCount=1 [p retain];//引用計數(shù)器+1
 NSLog(@"retainCount=%lu",[p retainCount]); 
//結(jié)果:
retainCount=2 [p release];//調(diào)用1次release引用計數(shù)器-1 NSLog(@"retainCount=%lu",[p retainCount]); 
//結(jié)果:
retainCount=1 [p release];
 //結(jié)果:Invoke Person's dealloc method. p=nil;
}
int main(int argc, const char * argv[]) {
 @autoreleasepool { 
Test1();
 } 
return 0;
}

注意:release會使引用計數(shù)減1,當(dāng)引用計數(shù)為0的時候,系統(tǒng)會自動調(diào)用dealloc銷毀對象,在對象release之后,需要將對象置nil,否則會成為野指針,在OC中,對一個空的對象發(fā)送消息是不會引起錯誤的。

內(nèi)存釋放的原則就是:誰分配,誰釋放

自動釋放池

這只是一種半自動的機(jī)制,有些操作還是需要我們手動設(shè)置的。自動內(nèi)存釋放使用@autoreleasepool關(guān)鍵字聲明一個代碼塊,如果一個對象在初始化時調(diào)用了autorelase方法,那么當(dāng)代碼塊執(zhí)行完之后,在塊中調(diào)用過autorelease方法的對象都會自動調(diào)用一次release方法。這樣一來就起到了自動釋放的作用,同時對象的銷毀過程也得到了延遲(統(tǒng)一調(diào)用release方法)。

代碼如下:

#import <Foundation/Foundation.h>
#import "Person.h"
int main(int argc, const char * argv[]) { 
@autoreleasepool {
 Person *person1=[[Person alloc]init];
 [person1 autorelease];//調(diào)用了autorelease方法后面就不需要手動調(diào)用release方法了
 person1.name=@"Kenshin";//由于autorelease是延遲釋放,所以這里仍然可以使用
person1 Person *person2=[[[Person alloc]initWithName:@"Kaoru"] autorelease];//調(diào)用了autorelease方法 
Person *person3=[Person personWithName:@"rosa"];//內(nèi)部已經(jīng)調(diào)用了autorelease,所以不需要手動釋放,這也符合內(nèi)存管理原則,因為這里并沒有alloc所以不需要release或者autorelease
 Person *person4=[Person personWithName:@"jack"];
 [person4 retain]; 
}
 /*結(jié)果:
 Invoke Person(rosa) dealloc method.
 Invoke Person(Kaoru) dealloc method. 
Invoke Person(Kenshin) dealloc method. 
*/ 
return 0;
}

對于自動內(nèi)存釋放簡單總結(jié)一下:

(1)autorelease方法不會改變對象的引用計數(shù)器,只是將這個對象放到自動釋放池中;
(2)自動釋放池實質(zhì)是當(dāng)自動釋放池銷毀后調(diào)用對象的release方法,不一定就能銷毀對象(例如如果一個對象的引用計數(shù)器>1則此時就無法銷毀);
(3)由于自動釋放池最后統(tǒng)一銷毀對象,因此如果一個操作比較占用內(nèi)存(對象比較多或者對象占用資源比較多),最好不要放到自動釋放池或者考慮放到多個自動釋放池;
(4)ObjC中類庫中的靜態(tài)方法一般都不需要手動釋放,內(nèi)部已經(jīng)調(diào)用了autorelease方法;

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,885評論 6 541
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,312評論 3 429
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,993評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,667評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 72,410評論 6 411
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,778評論 1 328
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,775評論 3 446
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,955評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,521評論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 41,266評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,468評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,998評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,696評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,095評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,385評論 1 294
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,193評論 3 398
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 48,431評論 2 378

推薦閱讀更多精彩內(nèi)容