1. 程式人生 > >黑馬程式設計師—OC語言基礎—記憶體管理

黑馬程式設計師—OC語言基礎—記憶體管理

之前我們已經提到過C語言中的記憶體儲存空間。有五大區域:堆、棧、自由儲存區、全域性\靜態儲存區和常量儲存區。

OC是以C語言為基礎的,所以也分這五大區域。

下面我們討論一下OC中記憶體管理的規律。

一、引用計數器

1.每個OC物件都有自己的引用計數器,是一個整數,即物件被引用的次數。

該計數器一旦誕生,次數就為1,當計數器為0時,該儲存空間就消失了。

所以我們要操縱該計數器來控制記憶體。

2.引用計數器的作用

1)當使用alloc、new或copy建立一個新物件時,新物件的引用計數器預設就是1;

2)當一個物件的引用計數器為0時,物件佔用的記憶體就會被系統回收,即若物件的計數器不為0,那麼在整個程式執行過程中,它佔用的記憶體就不可能被回收,除非整個程式已經推出。

3.引用計數器的操作

1)給物件傳送一條retain訊息(即呼叫retain方法),可以使引用計數器+1(retain方法返回物件本身)

[p retain];

2)給物件傳送一條release訊息可使引用計數器-1

[p release];

3)可給物件傳送retainCount訊息獲得當前的引用計數器值

[p retainCount];

4.物件的銷燬

1)當一個物件的引用計數器值為0時,那麼它將銷燬,其佔用的記憶體被系統回收

2)當一個物件被銷燬時,系統會自動向物件傳送一條dealloc訊息

3)一旦重寫了dealloc方法,就必須呼叫[super dealloc],並且放在最後呼叫

4)不要直接呼叫dealloc方法

5)一旦物件被回收了,它佔用的記憶體就不可再用,堅持用回導致程式崩潰。(這時野指標錯誤)

總結:為了更好地控制記憶體管理,有1個alloc就有1個release,有1個retain,就有1個release。

下面我們瞭解一下什麼是野指標。

二、野指標和空指標

當物件的引用計數器值為0,該物件銷燬,稱為殭屍物件。這時,p為野指標:指向殭屍物件(不可用的記憶體)的指標。

在引用計數器為0時,還呼叫[p release];,則執行報錯。

總結:

1.只要想用這個物件,就讓物件計數器+1

2.當不再用這個物件,計數器-1

3.誰建立,誰release

1)如果通過alloc、new或[mutable]copy來建立一個物件,那你必須呼叫release或autorelease;----->所以不是你建立的,就不用你去[auto]release

4.誰retain,誰release

只要你呼叫了retain,無論這個物件如何生成的,你都要呼叫release

總之,就是要:有始有終,有加就有減。

三、記憶體管理程式碼規範

1.只要呼叫了alloc,必須有release(autorelease)

2.set方法的程式碼規範

(1)基本資料型別:直接賦值

- (void)setAge:(int)age
{
    _age = age;
}

(2)OC物件型別
- (void)setCar:(Car *)car
{
    //1.判斷是不是新傳進來物件
    if(car != _car)
    {
        //2.對舊物件做一次release
        [_car release];
        //3.對新物件做一次retain
        _car = [car retain];
    }
}

3.dealloc方法的程式碼規範

1)一定要[super dealloc],且放到最後面

2)對當前物件所擁有的其他物件做一次release

- (void)dealloc
{
    [_car release];
    [super dealloc];
}

四、@property記憶體管理

[email protected]的記憶體管理

@property (retain)Book *book;

就相當於
- (void)setBook:(Book *)book
{
    if(_book !=book)
    {
        [_book release];
        _book = [book retain];
     }
}
retain的作用是生成的set方法裡面,release舊值,retain新值

[email protected]的引數

@property(retain)int age;這樣寫是不對的,因為基本資料型別不需要記憶體控制,因為會跟著程式塊自動清除。而OC型別不會。

1)set方法記憶體管理相關的引數

retain : release舊值,retain新值(適用於OC物件型別)

assign : 直接賦值(預設,適用於非OC物件型別)

copy   : release舊值,copy新值

2)是否要生成set方法

readwrite : 同時生成settergetter的宣告、實現(預設)

readonly  : 只會生成getter的宣告、實現

3.多執行緒管理

nonatomic : 效能高 (一般就用這個)

atomic    : 效能低(預設)

4.settergetter方法的名稱

setter : 決定了set方法的名稱,一定要有個冒號 :

getter : 決定了get方法的名稱(一般用在BOOL型別)

五、@class和迴圈retain

[email protected]的用法

@class Card;

該語句僅僅告訴編譯器,Card是一個類,但不知道Card類中又什麼變數。

一般情況下,如果兩個類,你有我,我有你,一般兩邊都用@class xxx;,所以涉及到迴圈引用就用@class。

但是@class比import少一個功能,即沒有將所有的功能拷貝過來。一般在日常開發中,如果要到.h檔案,則將#import "Person.h"放到.m檔案中宣告。

思考題:

為什麼開發中用@class而不用#import(除了NSObject用#import)?(@class與#import區別)

如果有上百個檔案#import同一個檔案或者這些檔案依次被#import,那麼一旦最開始的標頭檔案稍有改動,後面引用到這個檔案的所有類都需要重新編譯一遍,這樣效率很低,而用@class就不會出現這種問題。

2.迴圈retain

比如A物件retain了B物件,B物件retain了A物件,這樣會導致A物件和B物件永遠無法釋放。

遇到這種問題的解決辦法就是:當兩端互相利用時,應該一端用retain,一端用assign

六、autorelease

autorelease是半自動釋放記憶體,實際上只是延遲了釋放的時間。

基本格式:

@autoreleasepool
{   //開始代表建立了釋放池
    ......
}   //結束代表銷燬釋放池

缺點:不能精確控制釋放時間,所以不能亂用,所以儘量用release來精確控制。

因此,autorelease一般適用於佔用記憶體比較小的物件。

總結:

1.autorelease的基本用法

1)會將物件放到一個自動釋放池中

2)當自動釋放池被銷燬時,會對池子裡面的所有物件做一次release操作(不是銷燬物件,只是做-1操作)

3)會返回物件本身

4)呼叫完autorelease後,物件的計數器不變

2.autorelease好處

1)不用再關心物件釋放的時間

2)不用再關心什麼時候呼叫release

3.autorelease的使用注意

1)佔用記憶體較大的物件不要隨便使用autorelease

2)佔用記憶體較小的物件使用autorelease,沒有太大影響

4.錯誤寫法

1)alloc之後呼叫autorelease,又呼叫release

2)連續呼叫多次autorelease

5.自動釋放池

1)在iOS程式執行過程中,會建立無數個池子,這些池子都是以棧結構存在的。(先進來的後出去)

2)當一個物件呼叫autorelease方法時,會將這個物件放到棧頂的釋放池

6.autorelease使用細節

一個方法可以創建出不同型別的物件(誰呼叫我,我就建立誰);建立物件時,儘量考慮是否可以使用self,儘量用self。

注:沒有autoreleasepool,autorelease是沒有作用的。

七、ARC機制(Automatic Reference Counting 自動引用計數)

ARC機制是一個編譯器特性,這與Java中的垃圾回收是不一樣的,Java中的垃圾回收是執行時特性。

1.ARC原理

int main()
{
    Person *p = [[Person alloc]init];
    p = [[Person alloc]init];  //這一行就釋放Person物件的儲存空間
    NSLog(@"————");
    return 0;
}
釋放記憶體的位置是當強指標p指標不再指向物件的時候,這時物件就會銷燬。

總結:

ARC的判斷準則:只要沒有強指標指向物件,就會釋放物件。

指標分兩種:(1)強指標:預設情況下,所有的指標都是強指標(__strong);(2)弱指標:__weak

ARC中,只需將之前的retain換成strong,例如:

@property (nonatomic, strong)Dog *dog;

若寫為retain,但dealloc中不能用release了。

因此,在ARC中不允許呼叫release、retain、retainCount,允許重寫dealloc,但不允許呼叫[super dealloc];

@property的引數

*strong:成員變數是強指標(適用於OC物件型別)

*weak:成員變數是弱物件(適用於OC物件型別)

*assign:適用於非OC物件型別

注意:ARC的迴圈應用問題

這個問題和迴圈retain問題是一樣的。解決辦法也是類似的。

解決方案:

當兩端迴圈引用的時候,(1)ARC,一端用strong,一端用weak;(2)非ARC,一端用retain,一端用assign。

相關推薦

黑馬程式設計師OC語言基礎記憶體管理

之前我們已經提到過C語言中的記憶體儲存空間。有五大區域:堆、棧、自由儲存區、全域性\靜態儲存區和常量儲存區。 OC是以C語言為基礎的,所以也分這五大區域。 下面我們討論一下OC中記憶體管理的規律。 一、引用計數器 1.每個OC物件都有自己的引用計數器,是一個整數,即物件被

黑馬程式設計師——OC語言基礎——面向物件三大特性之多型

繼前兩篇博文梳理了一下我對OC中面向物件三大特性的封裝、繼承之後。最重要也是最不容易理解的多型概念終於到來。 個人認為多型在三大特性中是最為重要的,但是由於它的概念性不容易用語言描述清楚,所以我還是想引用視訊教程中老師說的那句經典。 多型的實質就是: 父類的指標 指向了

黑馬程式設計師-OC學習筆記-----記憶體管理

移動裝置的記憶體極其有限,每個app所能佔用的記憶體是有限制的.當app所佔用的記憶體較多時,系統會發出記憶體警告,這時得回收一些不需要再使用的記憶體空間。比如回收一些不需要使用的物件、變數等。基本的資料型別是放在記憶體的棧裡面,這是不需要我們去管理的,系統會自動回收。但是

黑馬程式設計師——OC筆記之記憶體管理

Objective-C提供了三種記憶體管理方式: MannulReference Counting(MRC,手動管理, iOS4.1之前的版本) automatic reference counting(ARC,自動引用計數,iOS4.1 之後推出的) garbage collection(垃圾回收)。iO

黑馬程式設計師----oc加強筆記----記憶體管理

                              引用計數器: 每個OC物件都有自己的引用計數器,是一個整數表示物件被引用的次數,即現在有多少東西在使用這個物件。物件剛被建立時,預設計數器值為1,當計數器的值變為0時,則物件銷燬。                 2)對引用計數器的操作     

黑馬程式設計師——Java語言基礎(一)

-----------android培訓、java培訓、java學習型技術部落格、期待與您交流!------------     對於Java初學者,學好Java語言基礎是非常重要的,這將影響將來程式設計的程式碼質量與效率。那麼Java語言基礎內容包括哪些呢?Java基礎內

黑馬程式設計師——C語言基礎——結構體相關練習

今天整理了C語言基礎學習過程中對結構體的一些知識,下面是程式碼片段: #include <stdio.h> #include <string.h> int main(int argc, const char * argv[]) { //定義

黑馬程式設計師——C語言基礎——檔案讀寫實戰

今天覆習的是C語言中另一塊比較重要的部分,檔案的讀寫操作。 在複習過後,還是以一道程式設計題來鞏固一下今天的學習成果: 檔案的讀寫操作程式設計實戰:         1.編寫一個函式,執行後可以錄入一句話(字串又使用者輸入)。         2.在每次輸入儲存後,

黑馬程式設計師——C語言基礎——指標程式設計練習題

------Java培訓、Android培訓、iOS培訓、.Net培訓、期待與您交流! ------- 今天覆習了一下指標的相關知識,並且在網上搜了一道小的程式設計練習題,大概題意如下: 有n個整數,使其前面各數順序向後移m個位置,最後m個數變成最前面的m個數。 大概的

黑馬程式設計師——Java語言基礎之陣列

八、陣列            1、定義:同一種資料型別的集合,其實質就是一個容器。            2、好處:自動給陣列的元素從0開始編號,方便操作。            3、格式1: 元素型別[ ]  陣列名= new 元素型別 [元素的個數或者陣列的長度] ;                

黑馬程式設計師-C語言基礎學習(一)

C語言學習筆記一 ---既然決定14年要好好的努力一次,那麼就不要再輕言放棄,不再在隨波逐流。只有努力過、拼搏過,才會知道自己行還是不行!為自己加油!--- ---總結的知識點可能有不正確的地方,如果有發現請留言給我,我一定及時更正,不讓錯誤的知識去誤導大家,有好的意見

黑馬程式設計師—C語言筆記—記憶體剖析

一、進位制 1、定義:是一種計數的方式,數值的表示形式。 2、常用的4種進位制: 二進位制以0b/0B開頭如int num1 = 0b1100; 八進位制以0開頭如int num2 = 014; 十進位制如 int num3 = 12; 十六進位制以0x/0X開頭如int num4=0xc;

黑馬程式設計師_java語言基礎組成

二、java語言基礎組成 1   關鍵字       其實就是某一個計算機語言對指定的單詞賦予了特殊的含義。        特點:體現上都是英文小寫。 2   識別符號       就是在程式中起的名字。       包含:0~9,a~z,$,_。        注意:1

黑馬程式設計師 OC基礎: 記憶體管理

記憶體管理 簡述 每個 oc 物件都有自己的引用計數器,是一個整數,表示”物件被引用的次數”.佔四位元組 計數器預設值為1 當為0時,物件佔用的記憶體會被系統回收. 引用的操作 給物件傳送一條 retain 計數器+1 給物件傳送一

黑馬程式設計師——OC基礎記憶體管理

=== 記憶體管理機制 === OC的區域性變數在程式碼塊結束時被系統銷燬, 記憶體被回收. OC的物件, 內部有引用計數器, 當引用計數器的值為0時, 被系統銷燬, 記憶體被回收. 區域性變數存放在棧中. 物件存放在堆中. 注意, 物件指標還是存放在棧中, 物件本身佔用的記憶體存放在堆中. 在OC

黑馬程式設計師——OC基礎---記憶體管理

1. 控制set方法的記憶體管理 retain : release舊值,retain新值(用於OC物件)  assign : 直接賦值,不做任何記憶體管理(預設,用於非OC物件型別) copy   : release舊值,copy新值(一般用於NSString *) 2.  控制需不需生成set方法 re

黑馬程式設計師——OC基礎——記憶體管理(一)

一,為什麼要進行記憶體管理 1,由於移動裝置的記憶體有限,所以每個APP所佔的記憶體也是有限制的,當APP所佔用的記憶體較多時,系統就會發出警告,這時就需要回收一些不需要繼續使用的記憶體空間,比如回收一些不再使用的物件和變數等。 任何繼承NSObject的物件,對其他的基

黑馬程式設計師------OC基礎-----記憶體管理

------Java培訓、Android培訓、iOS培訓、.Net培訓、期待與您交流! ------- 法則 誰建立記憶體誰就要釋放記憶體 管理機制 引用計數器 1使用alloc(相當於C語言中的malloc)為物件分配記憶體,使用dealloc(相當與C語言中的fre

黑馬程式設計師————OC記憶體管理_筆記整理(二)

一、@Prpperty引數 // 加上retain:表示生成的set方法,release舊值,retain新值 @property (retain) Book *book; // oc物件型別 //@property (nonatomic,retain) 類名 *屬性名

黑馬程式設計師——OC記憶體管理

1.記憶體的建立和釋放 讓我們以Object-c世界中最最簡單的申請記憶體方式展開,談談關於一個物件的生命週期。首先建立一個物件: id testObject = [[ClassName alloc] init]; //“ClassName”是任何你