記憶體管理屬性字串

2021-06-29 11:59:07 字數 3409 閱讀 5157

分類: ios開發

2014-05-26 14:36

726人閱讀收藏 

舉報**:

assign:指定setter方法用簡單的賦值,這是預設操作。你可以對標量型別(如int)使用這個屬性。你可以想象乙個float,它不是乙個物件,所以它不能retain、copy。assign指定setter方法用簡單的賦值,這是預設操作。你可以對標量型別(如int)使用這個屬性。你可以想象乙個float,它不是乙個物件,所以它不能retain、copy。

retain:指定retain應該在後面的物件上呼叫,前乙個值傳送一條release訊息。你可以想象乙個nsstring例項,它是乙個物件,而且你可能想要retain它。retain釋放舊的物件,將舊物件的值賦予輸入物件,再提高輸入物件的索引計數為

1 ,使用retain:

對其他nsobject和其子類 ,

retain

,是說明該屬性在賦值的時候,先

release

之前的值,然後再賦新值給屬性,引用再加1。

copy:指定應該使用物件的副本(深度複製),前乙個值傳送一條release訊息。基本上像retain,但是沒有增加引用計數,是分配一塊新的記憶體來放置它。

readonly:將只生成getter方法而不生成setter方法(getter方法沒有get字首)。

readwrite:預設屬性,將生成不帶額外引數的getter和setter方法(setter方法只有乙個引數)。

atomic:對於物件的預設屬性,就是setter/getter生成的方法是乙個原子操作。如果有多個執行緒同時呼叫setter的話,不會出現某乙個執行緒執行setter全部語句之前,另乙個執行緒開始執行setter的情況,相關於方法頭尾加了鎖一樣。

nonatomic:不保證setter/getter的原子性,多執行緒情況下資料可能會有問題。

copy: 建立乙個引用計數為1的物件,然後釋放舊的物件

retain:釋放舊的物件,將舊物件的值賦予輸入物件,再提高輸入物件的引用計數為 1

copy其實是建立了乙個相同的物件,而retain不是:

比如乙個nsstring物件,位址為0×1111,內容為@」str」

copy到另外乙個nsstring之 後,位址為0×2222,內容相同,新的物件retain為1, 舊有物件沒有變化

retain到另外乙個nsstring之 後,位址相同(建立乙個指標,指標拷貝),內容當然相同,這個物件的retain值+1

也就是說,retain是指標拷貝,copy是內容拷貝。在拷貝之前,都會釋放舊的物件。

1、使用copy: 對nsstring

2、使用retain: 對其他nsobject和其子類

1. 假設你用malloc分配了一塊記憶體,並且把它的位址賦值給了指標a,後來你希望指標b也共享這塊記憶體,於是你又把a賦值給(assign)了b。此時a和b指向同一塊記憶體,請問當a不再需要這塊記憶體,能否直接釋放它?答案是否定的,因為a並不知道b是否還在使用這塊記憶體,如果a釋放了,那麼b在使用這塊記憶體的時候會引起程式crash掉。

2. 了解到1中assign的問題,那麼如何解決?最簡單的乙個方法就是使用引用計數(reference counting),還是上面的那個例子,我們給那塊記憶體設乙個引用計數,當記憶體被分配並且賦值給a時,引用計數是1。當把a賦值給b時引用計數增加到2。這時如果a不再使用這塊記憶體,它只需要把引用計數減1,表明自己不再擁有這塊記憶體。b不再使用這塊記憶體時也把引用計數減1。當引用計數變為0的時候,代表該記憶體不再被任何指標所引用,系統可以把它直接釋放掉。

3. 上面兩點其實就是assign和retain的區別,assign就是直接賦值,從而可能引起1中的問題,當資料為int, float等原生型別時,可以使用assign。retain就如2中所述,使用了引用計數,retain引起引用計數加1, release引起引用計數減1,當引用計數為0時,dealloc函式被呼叫,記憶體被**。

4. copy是在你不希望a和b共享一塊記憶體時會使用到。a和b各自有自己的記憶體。

5. atomic和nonatomic用來決定編譯器生成的getter和setter是否為原子操作。在多執行緒環境下,原子操作是必要的,否則有可能引起錯誤的結果。加了atomic,setter函式會變成下面這樣:

[cpp]view plain

copy

"font-size:14px;"

>

if(property != newvalue) 

[cpp]view plain

copy

關於retain,copy,assign的區別問題其實困擾我很久了,因為在程式中不太常用到copy,assign,所以三者的具體差別一直不太明白。

按照我的理解,assign和retain的區別,就是引入了乙個計數器retaincount,就可以對乙個記憶體的釋放方便很多。copy,就是把原來的記憶體複製一遍,使各自都擁有乙個記憶體,這樣釋放的時候也不會出錯。assign: 簡單賦值,不更改索引計數(reference counting)。copy: 建立乙個索引計數為1的物件,然後釋放舊物件retain:釋放舊的物件,將舊物件的值賦予輸入物件,再提高輸入物件的索引計數為1使用assign: 對基礎資料型別 (nsinteger,cgfloat)和c資料型別(int, float, double, char, 等等)使用copy: 對nsstring使用retain: 對其他nsobject和其子類nonatomic,非原子性訪問,不加同步,多執行緒併發訪問會提高效能。注意,如果不加此屬性,則預設是兩個訪問方法都為原子型事務訪問

[cpp]view plain

copy

@property(nonatomic, retain) uitextfield *username 

//編譯時自動生成的**

- (uitextfield *) username   

- (void

) setusername:(uitextfield *)username_   

@property(retain) uitextfield *username //自動生成的**

- (uitextfield *) username   

return

retval;  

}  - (void

) setusername:(uitextfield *)username_   

}  

變長字串的記憶體管理

方法1 靜態記憶體 這裡有乙個方法來實現幫助函式 const char get string 複製 這個方法的好處是比較簡單,但是它也有很多嚴重的缺點。返回的字串可能比你期望的要長。無論你指定buf什麼樣的長度,它仍然可能太小。如果實際的字串太長,你或者超出陣列的範圍最終導致 悲慘的失敗,或者必須擅...

String 之字串與記憶體管理

github 的閱讀效果更佳 string a new string hello 是建立物件的過程,string 物件建立過程與其他物件建立的過程大致相同。但是在階段,會從常量池中尋找 hello 常量,若成功找到,則複製乙份到堆中,構成 string 型別物件的一部分 否則,在堆中自行建立 hel...

字串屬性函式

字串屬性方法 字串格式輸出對齊 1.str string learn 2.3.str.center 20 生成20個字元長度,str排中間 4.string learn 5.6.str.ljust 20 str左對齊 7.string learn 8.9.str.rjust 20 str右對齊 10...