C與OC的比較
在C語言中褐望,只存在內(nèi)存地址的分配和釋放勒庄。同一個內(nèi)存地址可以被多個指針指向。
int number = 4; // 定義一個數(shù)字
int *a = malloc(8); // 從堆區(qū)分配空間
*a = number; // 是指針a指向number
int *b = a; // 將指針a的值賦給指針b
free(b); // 釋放指針b
在上述代碼中瘫里,指針a和b指向的是一個同一個內(nèi)存地址实蔽,由指針a來開辟內(nèi)存空間,最后通過b來釋放內(nèi)存空間谨读。實際上這兩個指針是完全一模一樣的局装,即a = b。對a和b做操作劳殖,相當于是對他們指向的內(nèi)存空間做操作铐尚。
但是這樣會產(chǎn)生一個問題,在指針b被釋放之后哆姻,如同上面說的宣增,指針b被釋放,實際上是指針b指向的內(nèi)存空間被釋放掉了矛缨,也就是說爹脾,指針a指向的內(nèi)存空間也不存在了。如果我們使用指針a這個變量箕昭,就會報野指針錯誤灵妨。
為了改善這一方面,OC就有了引用計數(shù)機制:
NSObject *a = [[NSObject alloc] init]; // 在堆區(qū)分配內(nèi)存空間落竹,引用計數(shù)為1
NSObject *b = [a retain]; // 對象b通過retain持有對象a泌霍,引用計數(shù)+1
[a release]; // 釋放對象a,引用計數(shù)-1
NSLog(@"a: %@, b: %@", a, b); // a和b都可以使用
[b release]; // 釋放對象b // 引用計數(shù)-1述召,引用計數(shù)變?yōu)?
NSLog(@"a: %@, b: %@", a, b); // a和b被真正釋放了
在上述代碼中朱转,效果是和C語言是一樣的,對象a和對象b是完全相等的积暖,他們也是指向相同的內(nèi)存地址肋拔。但OC代碼中使用alloc來分配空間,retain用來持有對象呀酸,通過release來釋放對象(在OC中凉蜂,是不允許直接將對象釋放的,當引用計數(shù)為0的時候,dealloc方法系統(tǒng)會自動調(diào)用)窿吩。這里的release實際上的效果是對這片內(nèi)存地址上的引用計數(shù)-1茎杂,代表的意思雖然是釋放該對象,但其實在該內(nèi)存地址的引用計數(shù)不為o的時候纫雁,我們還可以繼續(xù)使用它煌往,這種做法只是在編譯上告知我們該對象已經(jīng)被釋放,當引用計數(shù)變?yōu)?的時候該片內(nèi)存地址就會被徹底釋放轧邪。就是一個對象創(chuàng)建了就一定會被釋放刽脖,當所有持有該內(nèi)存地址的對象被釋放了,該內(nèi)存地址才會被真正的釋放忌愚。
OC內(nèi)存管理上要注意的就是引用計數(shù)實際上是對內(nèi)存地址的持有者的一個計數(shù)曲管,而不是對象本身。創(chuàng)建對象的時候一定要使用alloc硕糊,retain院水,new,copy等關(guān)鍵詞來創(chuàng)建简十,而不能直接賦值(其實直接賦值也是可以的檬某,但該對象不能被釋放,只要以后不再使用這個對象就好了螟蝙。為了更加的安全恢恼,還是規(guī)范的寫更好一些)。釋放對象的方式有兩種:release和autorelease胰默。它們的含義是釋放了這個對象厅瞎,實際作用都是給引用計數(shù)-1,而不是去釋放內(nèi)存地址初坠。所以當釋放了這個對象之后,如果還有其他對象持有該內(nèi)存地址彭雾,就可以繼續(xù)使用該對象碟刺,但是為了安全起見,當對象不在使用的時候?qū)⑵溽尫攀碓停尫胖蟛灰偃ナ褂冕尫藕蟮膶ο蟀牍痢H绻搶ο笫俏ㄒ坏某钟姓撸蜁鹨爸羔槨?/p>
我們來看一下下面的代碼:
int number = 4;
int *a = malloc(8);
a = &number;
free(a);
在上面的代碼中吴菠,我們可以看到指針a分配了8個字節(jié)的地址者填,但是后來將a又指向了number的地址,最后釋放a做葵。這樣釋放的其實釋放的是number的地址占哟,而number是在棧區(qū)中的,不能被手動釋放,而原來的內(nèi)存地址現(xiàn)在由于沒有指向而無法得到釋放榨乎。這樣就造成了內(nèi)存泄漏怎燥。
在OC中也會有這樣的情況:
NSLog(@"%@", [[NSObject alloc] init]);
NSLog(@"%@", [[[NSObject alloc] init] autorelease]);
類似于C語言一樣的內(nèi)存泄漏我們就不說了,我們來講一講對象作為參數(shù)的時候蜜暑。比較上面兩行代碼铐姚,都打印了一下NSObject的一個實例,這個實例是作為參數(shù)而被創(chuàng)建的肛捍,該片內(nèi)存地址沒有任何持有者隐绵,但是內(nèi)存空間確實是被開辟出來了。對于這樣的情況我們不可以使用release來立即釋放拙毫,通過持有對象依许,調(diào)用對象,釋放對象流程就太過繁瑣了恬偷,所以這里可以使用autorelease關(guān)鍵詞來自動釋放對象悍手,這樣在該對象被使用完后,該對象會被自動釋放袍患。便利構(gòu)造器就是在這樣的情況下使用的坦康。