Objective-C基础笔记(3)OC的内存管理
Objective-C的內存基本管理
在OC中每一個變量都保存著引用計數器,當這個對象的引用計數器為0的時候該對象會被回收。當使用alloc、new或者copy創建一個對象的時候,對象的引用計數器被置為1.
給對象發送一條retain消息,能夠使引用計數器+1.
給對象發送一條release消息,能夠使引用計數器-1.
當OC被銷毀的時候會發送一條dealloc消息(不要直接調用,由系統調用),能夠重寫dealloc方法。在該方法中釋放相關資源。
能夠給對象發送retainCount消息獲取對象的當前引用計數器。
首先我們新建一個project
接下來將project的設置里面將ARC禁掉
Book.h文件
#import <Foundation/Foundation.h>@interface Book : NSObject@property float price;- (id)initBook:(float)price;@endBook.m文件#import "Book.h"@implementation Book@synthesize price = _price;//構造函數 - (id)initBook:(float)price {if(self = [super init]){_price = price;}NSLog(@"價格是%f的書購買了", _price);return self; }//析構函數 - (void)dealloc {NSLog(@"價格為%f的書被釋放了", _price);[super dealloc]; }@endStudent.h文件#import <Foundation/Foundation.h> #import "Book.h"@interface Student : NSObject@property int age; @property Book *book;- (void)setBook:(Book *)book;- (id)initStudent:(int)age;@endStudent.m文件#import "Student.h" #import "Book.h"@implementation Student@synthesize age = _age; @synthesize book = _book;- (void)setBook:(Book *)book {if(_book != book){//先對原來的書計數器減一//假設之前為nil不會出錯(和java中的空指針不同)[_book release];[book retain];_book = book;} }//構造函數 - (id)initStudent:(int)age {if(self = [super init]) {_age = age;}NSLog(@"年齡為%d的學生被創建了", _age);return self; }//析構函數 - (void)dealloc{[_book release];NSLog(@"年齡為%d的學生被釋放了", _age);[super dealloc]; }@end main.m文件#import <Foundation/Foundation.h> #import "Student.h" #import "Book.h"void buyBook(Student *stu) {Book *book1 = [[Book alloc] initBook:101.5]; //誰創建誰釋放stu.book = book1;[book1 release];Book *book2 = [[Book alloc] initBook:98.5];stu.book = book2;[book2 release]; }void readBook(Student *stu) {NSLog(@"年齡是%i的學生在讀價格為%f的書", stu.age, stu.book.price); }int main(int argc, const char * argv[]) {@autoreleasepool {//計數器為1Student *stu = [[Student alloc] initStudent:21];//買書buyBook(stu);//看書readBook(stu);//計數器清0,釋放內存[stu release];}return 0; } 輸出結果:2014-11-13 23:11:19.510 內存管理[698:46519] 年齡為21的學生被創建了
2014-11-13 23:11:19.512 內存管理[698:46519] 價格是101.500000的書購買了
2014-11-13 23:11:19.512 內存管理[698:46519] 價格是98.500000的書購買了
2014-11-13 23:11:19.512 內存管理[698:46519] 價格為101.500000的書被釋放了
2014-11-13 23:11:19.512 內存管理[698:46519] 年齡是21的學生在讀價格為98.500000的書
2014-11-13 23:11:19.512 內存管理[698:46519] 價格為98.500000的書被釋放了
2014-11-13 23:11:19.512 內存管理[698:46519] 年齡為21的學生被釋放了
@classkeyword
通常引用一個類有兩種方法。一種是通過#import,還有一種是通過@class.#import 的方式會將頭文件里的全部信息引入。
@class 的方式僅僅是說明它是一個類(假如僅僅是聲明一個類就不用使用#import).
#import <Foundation/Foundation.h>@class Book; //聲明Book是一個類@interface Student : NSObject {Book *_book; }@property int age; @property Book *book;- (void)setBook:(Book *)book;- (id)initStudent:(int)age;@end另外。Student.m中的析構函數我們能夠做例如以下改動//析構函數 - (void)dealloc{self.book = nil; //調用setter方法[_book release];NSLog(@"年齡為%d的學生被釋放了", _age);[super dealloc]; }self.book = nil; 會調用setter方法。釋放對象并將當前類Student的屬性_book設為nil.@property的參數
@property的參數格式: @property (參數1, 參數2,...) 類型 名字;參數主要分為4類:
讀寫屬性:readwrite / readonly (是否生成get和set方法)
setter處理: assign / retain / copy ?(和內存管理相關)
原子性:atomic / nonatomic ? (這兩個和多線程相關)
set和get方法名稱相關參數:setter(設置生成的set方法名稱)/ getter(設置生成的get方法名稱)
改變set和get名稱,多是用于BOOL類型的變量
@property (nonatomic, assign, setter = abc:) int height; ?設置set方法名稱為 abc:
說明:
readonly代表僅僅生成getter方法,默認是readwrite
assing默認(set方法直接賦值),copy是setter方法release舊值,再copy新值
retain 要生成符合內存管理原則的set方法(應用于對象類型)(注意:在dealloc方法中釋放屬性對象)
atomic(默認),保證getter和setter的原子性。提供多線程安全訪問,nonatomic性能高。所以通常是選擇nonatomic.
#import <Foundation/Foundation.h>@class Book; //聲明Book是一個類@interface Student : NSObject //assign參數代表set方法直接賦值(默認的) //getter方法是指定getter方法的名字 @property (nonatomic, assign, getter=getStudentAge) int age; //這里的retain代表:release舊值,retain新值 //(注意,基本數據類型不能寫retain參數) @property (nonatomic, retain) Book *book;- (void)setBook:(Book *)book;- (id)initStudent:(int)age;@end#import "Student.h" #import "Book.h"@implementation Student//構造函數 - (id)initStudent:(int)age {if(self = [super init]) {_age = age;}NSLog(@"年齡為%d的學生被創建了", _age);return self; }//析構函數 - (void)dealloc{self.book = nil; //調用setter方法[_book release];NSLog(@"年齡為%d的學生被釋放了", _age);[super dealloc]; }@end自己主動釋放池
自己主動釋放池是OC里面的一種內存自己主動回收機制,一般能夠將一些暫時變量加入到自己主動釋放池中。統一回收釋放。當自己主動釋放池銷毀時。池里的全部對象都會調用一次release方法。OC對象僅僅須要發送一條autorelease消息。就會把這個對象加入到近期的自己主動釋放池中(棧頂的釋放池)。autorelease實際上僅僅是把release的調用延遲了,對于每一次autorelease,系統僅僅是把該對象放入當前的autorelease pool中,當該pool被釋放時,該pool中的全部對象會調用一次release方法。
#import "Student.h" #import "Book.h"@implementation Student//創建靜態方法構造對象 + (id)student {Student *stu = [[[Student alloc] init] autorelease];return stu; }//創建帶參數的靜態方法構造對象 + (id)studentWithAge:(int)age {Student *stu = [self student];stu.age = age;return stu; }//構造函數 - (id)initStudent:(int)age {if(self = [super init]) {_age = age;}NSLog(@"年齡為%d的學生被創建了", _age);return self; }//析構函數 - (void)dealloc{self.book = nil; //調用setter方法[_book release];NSLog(@"年齡為%d的學生被釋放了", _age);[super dealloc]; }@endint main(int argc, const char * argv[]) {//代表創建一個自己主動釋放池@autoreleasepool {//第一種寫法Student *stu = [[[Student alloc] initStudent:21] autorelease];Student *stu1 = [[[Student alloc] initStudent:21] autorelease];} //當括號結束后,池子將被銷毀//假設自己主動釋放池被銷毀。池里面的全部對象都會調用release方法@autoreleasepool {//另外一種寫法Student *stu2 = [[Student alloc] initStudent:21];[stu2 autorelease];}@autoreleasepool {//第三種寫法(推薦)//不用手動釋放Student *stu3 = [Student student];}return 0; }注意:
1、假設某個對象調用了多次autorelease方法,則在自己主動釋放池銷毀的時候會調用多次release方法進行釋放。
例如以下:
@autoreleasepool {Person *p = [[Person alloc] init];[p autorelease];[p autorelease];}p對象會被釋放兩次。2、假設嵌套autoreleasepool。那么對象將在調用了autorelease(加入到池子)的每層自己主動釋放池結束的時候調用一次autorelease,例如以下:
Person *p = [[Person alloc] init];@autoreleasepool {@autoreleasepool {[p autorelease];}}對象將在第7行被釋放,而以下的情況會出現野指針異常 Person *p = [[Person alloc] init];@autoreleasepool {[p autorelease];@autoreleasepool {[p autorelease];}}轉載于:https://www.cnblogs.com/clnchanpin/p/7069053.html
總結
以上是生活随笔為你收集整理的Objective-C基础笔记(3)OC的内存管理的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 音视频播放流程
- 下一篇: ActiveMQ消息传送机制以及ACK机