OC第三天(內存管理)

內存管理:

1.作用範圍:

任何繼承了NSObject的對象,堆基本數據類型無效如:int a ,float price;;

2.原理:

每個對象內部都保存了一個與之相關的整數,稱爲引用計數器,

當使用alloc   new   copy創建一個對象的時候,對象的引用計數器被設置爲1

 

每給對象發送一次retain消息,可以使引用計數器+1

給對象發送一條release消息,可以使引用計數器-1

 

當一個對象的引用計數器爲0時,那麼它將被銷燬,其佔用的內存被系統回收,OC也會自動向對象發送一條dealloc消息,一般會重寫dealloc方法,在這裏,釋放相關資源,一定不要直接調用dealloc方法:

 

可以給對象發送retaincount消息,獲得當前的因數計數器數值。

 

 

 

3.retain release

1,如果你想知道一個對象是不是被回收,方法:重寫父類的dealloc方法:

注意:一定要調用super的dealloc方法,而且最後放在最後面調用。([super dealloc ])

 

2.如果一個對象調用了release 的操作,並且他的引用計數器已經爲0,如果你再次調用他的release方法:這時候就會發生野指針錯誤:

野指針錯誤:你調用了本不屬於你的內存空間,你既然已經釋放了本來你的內存,那麼現在那塊內存已經不屬於你了,你在調用release方法,說明你又聲明那塊內存是屬於你的,這時候就會發生野指針 錯誤。

 

注意:當一個對象retain0的時候,這時候你就不能再調用他的retainCound方法,因爲一個被釋放的對象,沒有內存,不再去進行訪問會發生野指針錯誤。

 

3.如果你在創建對象的時候,加上autorelease,那麼編譯器會在一個適當的時機釋放對象,這                     樣就不需要你自己手動釋放對象的內存了

 

 

4.內存管理法則:

1.誰創建,誰釋放(“誰污染,誰治理”),如果你通過alloc ,new ,copy來創建一個對象,那麼你必須調用release或autorelease ,如果不是你創建的,你就不用去釋放。

2.一般除了alloc ,new  copy之外的方法創建的對象都被聲明瞭autorelease

3.retain ,誰release ,只要你調用了retain ,無論這個對象是如何產生的,你都要調用release;

 

 

5.對象之間的內存管理:

前提:如果一個類A作爲另外一個類B的成員變量,並且訪問A的數據成員的是否,如果在main函數中調用了類B的一個方法,這時候會調用A的對象進行初始化A的成員變量,當在該方法中銷燬後,類B又訪問了一個方法2,這時候仍然讓類A的對象進行初始化操作,這時候會出現野指針錯誤,

原因:由於在方法1中已經釋放了A對象,所以A對象所指向的成員變量的內存回收,如果你再進行調用,就會指向一個不屬於自己的內存空間,這是很危險的。

 

解決辦法,在set方法裏裏面設施對象的retain操作,並進行release,前提,是判斷傳進來的對象是不是本身。如果是本身那就釋放掉原來對象的指向,如果是一個新的,那就沒有必要進行release,因爲,新對象本來計數器爲0.你再release,就會錯誤;

代碼如下:

B 中的.M文件

- (id)initWithAge:(int)age{

   if ( self= [super init]) {

       _age = age;

   }

   

    return self;

}

 

#pragma mark 回收對象

- (void)dealloc {

    // 釋放Book對象

   [_book release];

   

    //[self.book release];

   

    NSLog(@"student:%i被銷燬了", _age);

   [super dealloc];

}

 

#pragma mark - gettersetter

 

- (void)setBook:(Book*)book {

   if (_book!= book) {

        // 先釋放舊的成員變量

       [_book release];

        // retain新傳進來的對象

       _book = [book retain];

   }

}

 

- (Book *)book {

   return _book;

}

 

#pragma mark - 公共方法

#pragma mark 讀書

- (void)readBook {

    NSLog(@"當前讀的書是:%f", _book.price);

}

 

 

 

main函數:

void test(Student*stu) {

    // book:1  引用計數器

   Book *book = [[Book alloc] initWithPrice:3.5];

 

    // book:2

   stu.book = book;

 

    // book:1

   [book release];

       

     //book2:1

   Book *book2 = [[Book alloc] initWithPrice:4.5];

     //book2:2

   stu.book = book2;

    // book2:2

   stu.book = book2;

    // book2:1

   [book2 release];

   

    // book2:1

    stu.book = book2;//如果再次調用,book2的retaiin也不會變

}

 

void test1(Student*stu) {

   [stu readBook];

}

 

int main(intargc, const char* argv[])

{

 

    @autoreleasepool {

       // stu:1

       Student *stu = [[Student alloc] initWithAge:10];

       

       // stu:1

        //book:1

        //book2:1

       test(stu);

       

       // stu:1

        //book:1

        //book2:1

       test1(stu);

       

       // stu:0

        //book2:0

        //book:1

       [stu release];

   }

   return 0;

}

 

發佈了58 篇原創文章 · 獲贊 12 · 訪問量 10萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章