Objective-C 記憶體管理,

來源:互聯網
上載者:User

Objective-C 記憶體管理,

管理範圍:任何繼承NSObject的對象,基礎資料型別 (Elementary Data Type)不用進行管理

本質原因:因為對象和基礎資料型別 (Elementary Data Type)在系統中的儲存空間不一樣,局部變數主要存放在棧中,而Object Storage Service於堆中,當代碼塊結束時這個代碼塊中涉及的所有局部變數會被回收,指向對象的指標也被回收,此時對象已經沒有指標指向,但依然存在於記憶體中,造成記憶體泄露。

出現原因:

1.記憶體溢出:沒有指向對象的指標,但是對象沒有被回收

2.野指標異常:指向殭屍對象的指標,殭屍對象是記憶體被回收的對象。

給null 指標發送訊息不會報錯

在每個oc對象內部,都有專門的4個位元組的儲存空間來儲存引用計數

 

記憶體管理方式:

1.手工引用計數(manual reference counting)

2.自動引用計數(auto reference counting)

MRC的記憶體管理機制:引用計數

ARC是基於MRC的,ARC是編譯器特性,而不是運行時特性

記憶體管理原則

(一)原則 只要還有人在使用某個對象,那麼這個對象就不會被回收; 只要你想使用這個對象,那麼就應該讓這個對象的引用計數器+ 1 當你不想使用這個對象時,應該讓對象的引用計數器- 1  (二)誰建立,誰release (1)如果你通過alloc, new ,copy來建立了一個對象,那麼你就必須調用release或者autorelease方法 (2)不是你建立的就不用你去負責   (三)誰retain,誰release 只要你調用了retain,無論這個對象時如何產生的,你都要調用release  (四)總結 有始有終,有加就應該有減。曾經讓某個對象計數器加 1 ,就應該讓其在最後- 1 . 屬性賦值的記憶體管理:retain:應該先對舊的對象執行release,然後對新的對象retain(適用oc物件類型)assign:直接賦值copy:對舊的對象執行release,對新的對象copy

retain下的屬性內部實現

- (void) setName:(NSString *)name {

  if(_name != name) {

    [_name release];

    _name = [name retain];

  }

}

- (NSString *) name {

  return [[_name retain] autorelease];

}

使用retain讓對象的引用計數加1,如果單純賦值沒有使用retain,對象的引用計數不會變化

assign、retain、copy對應不同的setter實現。為執行個體變數賦值時,盡量使用setter方法,再次賦值時,會把之前值release。

dealloc在對象引用計數為0時自動調用,不要顯式調用。

dealloc實現內部,先要釋放執行個體變數,然後執行[super dealloc]。

便利構造器的記憶體管理是藉助autorelease實現的。

集合會管理自己的元素。 KVC是一種間接訪問執行個體變數的方法。 ARC系統管理記憶體,不需要開發人員手動管理。 

 

當對象autorelease時,會被添加到autoreleasepool中,當autoreleasepool被銷毀時,對象被銷毀

系統內建的方法中,如果不包含alloc,new,copy等,則這些方法返回的對象都是autorelease的,如[NSDate date]; 

開發中經常會寫一些類方法來快速建立一個autorelease對象,建立對象時不要直接使用類名,而是使用self

nonatomic設定屬性setter,getter操作不是原子性的,不是安全執行緒的,atomic是原子性的

 

OC中copy的作用是:利用一個來源物件產生一個副本對象(copy必須遵循NSCopying協議)

特點:1、修改來源物件的屬性和行為,不會影響副本對象。

         2、修改副本對象的屬性和行為,不會影響來源物件。

 使用方式:

一個對象可以調用copy或mutableCopy方法來建立一個副本對象。

1、copy:建立的時不可變副本(如NSString、NSArray、NSDictionary)。

2、mutableCopy:建立的可變副本(如NSMutableString、NSMutableArray、NSMutableDictionary)。

 

使用copy功能的前提:

1、copy:需要遵守NSCopying協議,實現copyWithZone:方法。

@protocol NSCopying

 - (id)copyWithZone:(NSZone *)zone;

@end

 2、mutableCopy : 需要遵守NSMutableCopying協議,實現mutableCopyWithZone:方法

@protocol NSMutableCopying

 - (id)mutableCopyWithZone:(NSZone *)zone;

@end

只有來源物件和副本對象都不可變時,才是淺複製,其他都是深複製。

深複製和淺複製的區別:

1.深複製(深拷貝、內容拷貝、deep copy):

      特點:1、來源物件和副本對象是不同的兩個對象; 

               2、來源物件引用計數器不變,副本對象計數器為1(因為是新產生的)。

      本質:產生了新對象。

2.淺複製(淺拷貝、指標拷貝、shallow copy):

      特點:1、來源物件和副本對象是同一對象; 

               2、來源物件(副本對象)引用計數器+1,相當於做一次retain操作。

      本質:沒有產生新對象。

 

淺拷貝:對象開闢新的空間,對象的記憶體位址不同,執行個體變數指向同一塊記憶體

- (id) copyWithZone:(NSZone *)zone

{

    Person *p = [[Person allocWithZone:zone] init];

    p.string = self.string;

    return p;

}

 

深拷貝:對象和執行個體變數的記憶體位址都不同

- (id) copyWithZone:(NSZone *)zone

{

    Person *p1 = [[Person allocWithZone:zone] init];

    p1.string = [self mutableCopy];

    return p1;

}

 

偽拷貝:

- (id) copyWithZone:(NSZone *)zone

{

    return [self retain];

}

 

附、ARC的特點總結:

1)不允許調用release,retain,retainCount

2)允許重寫dealloc,但是不允許調用[super dealloc]

3@property的參數:         Strong:相當於原來的retain(適用於OC物件類型),成員變數是強指標         Weak:相當於原來的assign,(適用於oc物件類型),成員變數是弱指標         Assign:適用於非OC物件類型(基礎類型)  補充 讓程式相容ARC和非ARC部分。轉變為非ARC  -fno-objc-arc  轉變為ARC的, -f-objc-arc 。 ARC也需要考慮循環參考問題:一端使用retain,另一端使用assign。 提示:字串是特殊的對象,但不需要使用release手動釋放,這種字串對象預設就是autorelease的,不用額外的去管記憶體。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.