記憶體管理
1.什麼是arc?
arc是automatic reference counting自動引用計數,在程式編譯時自動加入retain/release。在物件被建立時retain count+1,在物件被release時count-1,當count=0時,銷毀物件。程式中加入autoreleasepool物件會由系統自動加上autorelease方法,如果該物件引用計數為0,則銷毀。那麼arc是為了解決mrc手動管理記憶體存在的一些而誕生的。
mrc下記憶體管理的缺點:
雖然arc給我們程式設計帶來的很多好多,但也可能出現記憶體洩露。如下面兩種情況:
2.block一般用那個關鍵字修飾,為什麼?
block一般使用copy關鍵之進行修飾,block使用copy是從mrc遺留下來的「傳統」,在mrc中,方法內容的block是在棧區的,使用copy可以把它放到堆區。但在arc中寫不寫都行:編譯器自動對block進行了copy操作。
3、@property宣告的nsstring(或nsarray,nsdictionary)經常使用copy關鍵字,為什麼?如果改用strong關鍵字,可能造成什麼問題?
答:用@property宣告 nsstring、nsarray、nsdictionary 經常使用copy關鍵字,是因為他們有對應的可變型別:nsmutablestring、nsmutablearray、nsmutabledictionary,他們之間可能進行賦值操作,為確保物件中的字串值不會無意間變動,應該在設定新屬性值時拷貝乙份。
如果我們使用是strong,那麼這個屬性就有可能指向乙個可變物件,如果這個可變物件在外部被修改了,那麼會影響該屬性。
copy此特質所表達的所屬關係與strong類似。然而設定方法並不保留新值,而是將其「拷貝」 (copy)。 當屬性型別為nsstring時,經常用此特質來保護其封裝性,因為傳遞給設定方法的新值有可能指向乙個nsmutablestring類的例項。這個類是nsstring的子類,表示一種可修改其值的字串,此時若是不拷貝字串,那麼設定完屬性之後,字串的值就可能會在物件不知情的情況下遭人更改。所以,這時就要拷貝乙份「不可變」 (immutable)的字串,確保物件中的字串值不會無意間變動。只要實現屬性所用的物件是「可變的」 (mutable),就應該在設定新屬性值時拷貝乙份。
copy相當於生成乙個新的屬性,占用新的記憶體空間,strong相當於乙個指標,指向原來的記憶體空間
4.runloop、autorelease pool以及執行緒之間的關係。
每個執行緒(包含主線程)都有乙個runloop。對於每乙個runloop,系統會隱式建立乙個autorelease pool,這樣所有的release pool會構成乙個像callstack一樣的乙個棧式結構,在每乙個runloop結束時,當前棧頂的autorelease pool會被銷毀,這樣這個pool裡的每個object會被release。
5.@property 的本質是什麼?ivar、getter、setter 是如何生成並新增到這個類中的。
「屬性」(property)有兩大概念:ivar(例項變數)、訪問方法(access method=getter),即@property = ivar + getter + setter。
例如下面的這個類:
1
2
3
4
@inte***ce wbtextview :uitextview
@property (nonatomic,copy)nsstring *placehold;
@property (nonatomic,copy)uicolor *placeholdcolor;
@end
類完成屬性的定以後,編譯器會自動編寫訪問這些屬性的方法(自動合成autosynthesis),上述**寫出來的類等效與下面的**:
1
2
3
4
5
6
@inte***ce wbtextview :uitextview
- (nsstring *)placehold;
-(void)setplacehold:(nsstring *)placehold;
-(uicolor *)placeholdcolor;
-(void)setplaceholdcolor:(uicolor *)placeholdcolor;
@end
6.分別寫乙個setter方法用於完成@property (nonatomic,retain)nsstring *name和@property (nonatomic,copy) nsstring *name
retain屬性的setter方法是保留新值並釋放舊值,然後更新例項變數,令其指向新值。順序很重要。假如還未保留新值就先把舊值釋放了,而且兩個值又指向同乙個物件,先執行的release操作就可能導致系統將此物件永久**。
1
2
3
4
5
6
7
8
9
10
11
12
-(void)setname:(nsstring *)name
-(void)setname:(nsstring *)name
7.說說assign vs weak,_block vs _weak的區別
assign適用於基本資料型別,weak是適用於nsobject物件,並且是乙個弱引用。
assign其實頁可以用來修飾物件,那麼為什麼不用它呢?因為被assign修飾的物件在釋放之後,指標的位址還是存在的,也就是說指標並沒有被置為nil。如果在後續記憶體分配中,剛才分到了這塊位址,程式就會崩潰掉。而weak修飾的物件在釋放之後,指標位址會被置為nil。
_block是用來修飾乙個變數,這個變數就可以在block中被修改。
_block:使用_block修飾的變數在block**塊中會被retain(arc下,mrc下不會retain)
_weak:使用_weak修飾的變數不會在block**塊中被retain
8.請說出下面**是否有問題,如果有問題請修改?
12
3
4
5
6
@autoreleasepool
}
記憶體管理的原則:如果對乙個物件使用了alloc、copy、retain,那麼你必須使用相應的release或者autorelease。咋一看,這道題目有alloc,也有autorelease,兩者對應起來,應該沒問題。但autorelease雖然會使引用計數減一,但是它並不是立即減一,它的本質功能只是把物件放到離他最近的自動釋放池裡。當自動釋放池銷毀了,才會向自動釋放池中的每乙個物件傳送release訊息。這道題的問題就在autorelease。因為largenumber是乙個很大的數,autorelease又不能使引用計數立即減一,所以在迴圈結束前會造成記憶體溢位的問題。
解決方案如下:
1
2
3
4
5
6
7
8
@autoreleasepool
}
}
在迴圈內部再加乙個自動釋放池,這樣就能保證每建立乙個物件就能及時釋放。
9.請問下面**是否有問題,如有問題請修改?
12
3
4
5
6
7
8
9
@autoreleasepool
這道題跟第8題一樣存在記憶體洩露問題,1.記憶體洩露 2.指向常量區的物件不能release。
指標變數str原本指向一塊開闢的堆區空間,但是經過重新給str賦值,str的指向發生了變化,由原來指向堆區空間,到指向常量區。常量區的變數根本不需要釋放,這就導致了原來開闢的堆區空間沒有釋放,照成記憶體洩露。
10.什麼情況下使用weak關鍵字,相比assign有什麼不同?什麼情況使用weak關鍵字?
不同點:
11.記憶體管理語義(assign、strong、weak等的區別)
copy關鍵字的使用
平時我們使用物件之間的傳值都是採用retain count 1的方式,這種方式的適用於當物件的某屬性的值改變時,引用該物件的不同指標會同時改變,因為這兩個指標指向的是同乙個記憶體位址,但如果需求是,當乙個指標執行的物件屬性值發生改變時,不影響另乙個物件,那麼需要分配兩個不同的記憶體位址,也就是說,我...
strong和copy的區別
問題描述 在定義乙個類的property時候,為property選擇strong還是copy特別注意和研究明白的,如果property是nsstring或者nsarray及其子類的時候,最好選擇使用copy屬性修飾。為什麼呢?這是為了防止賦值給它的是可變的資料,如果可變的資料發生了變化,那麼該pro...
this關鍵字和super關鍵字
this關鍵字和super關鍵字都必須放在構造方法的第一行,所有兩個關鍵字不能同時存在,任選其一即可,只需保證子類的所有構造方法呼叫父類的構造方法即可 this關鍵字的應用 this關鍵字用於區分區域性變數和成員變數的同名問題 有this關鍵字的是成員變數,或者是誰呼叫我,訪問的就是誰 this關鍵...