内存管理Memoryamp;nbsp;OC——第九天
生活随笔
收集整理的這篇文章主要介紹了
内存管理Memoryamp;nbsp;OC——第九天
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
1、? ? 內存管理方式 ? ? ? ?垃圾回收機制:(Garbage Collection),有系統管理內存,開發人員需要管理 ? ? ? ?注:OC從2.0之后就開始支持垃圾回收機制,但是只適用于OS開發,(蘋果電腦的操作系統),我們iOS平臺是不支持垃圾回收機制;(面試題) 不支持垃圾回收機制,OC是如何管理內存的呢? ???????//內存不釋放 就叫內存泄露 //OC通過引入計數器管理內存
??????? //圖中需要照明的人數,就代表引用計數
??????? //1.當第一人"需要照明",引用計數+1 ??? 有0-->1
??????? //2.當第二個人"需要照明",引用計數+1 ??? 有1-->2
??????? //3.當第二個人"需要照明",引用計數+1 ??? 有2-->3
??????? //4.當有一個人"不需要照明",引用計數-1 ??? 有3-->2
??????? //5.當再有一個人"不需要照明",引用計數-1 ??? 有2-->1 ???????//6.當再有一個人"不需要照明",引用計數-1 ??? 有1-->0 2、iOS平臺下適用計數器如何管理內存,有兩種方式 ? ??1.MRC:(Manual Reference Counting),手動引入計數器,有開發人員通過手動引入計數器來管理內存。 ? ? ? 2.ARC:(Automatic Reference Counting),自動引入計數器,由系統通過引入計數器管理內存 ???????//學習好MRC是為了更好使用ARC,iOS5.0之后就有了ARC; ARC和MRC的混編 ? ? ? ? 1.如果工程環境是ARC,而部分文件使用了MRC,使用一個參數???-fno-objc-arc ? ? ? ?2.如果工程環境是MRC,而部分文件使用了ARC,使用一個參數 ???-fobjc-arc ============================================================== 例子:? 1.自己創建的對象自己持有; Person.h @interface Person : NSObject //名字的屬性 @property (nonatomic,copy)NSString *name; @end
Person.m @implementation Person
//dealloc 方法是對象被銷毀的時候自動調用的方法,不需要手動調用,由于dealloc方法是重寫的父類,所以重寫此方法的時候,一定要把父類的方法內容也寫上 - (void)dealloc? ?{ ??NSLog(@"Person%@對象被銷毀了",_name);
???//以后重寫dealloc方法時一定調用[super dealloc];? 且此方法一定要寫在最下面 ??? [super dealloc]; } @end
main.m Person *p = [[Person alloc]init];//alloc會造成對象的引用計數器由0-->1 ??????? p.name = @"緩緩"; ??????? //如何判斷一個對象是否被持有,就看它的引用計數
??????? //retainCount :對象的引用計數 ???????NSLog(@"%lu",p.retainCount); //計數器為1 ??????? //如果自己創建的對象不使用時,釋放對象,使用release
??????? [p release];
// ??? NSLog(@"%lu",p.retainCount); ?????對象死了就不能再使用它了 // ??? [p release];??? 不要過度釋放,也等于操作僵尸對象 ?Person *p2 = [[Person alloc]init]; ? //0--->1 ??????? p2.name = @"武媚娘"; 3、retain可以讓對象的引用計數 +1
??????? //非自己創建的對象,自己也能持有
???????? p2 =? [p2 retain]; //由1--->2
??????? NSLog(@"%lu",p2.retainCount);
???????
????????//非自己創建的對象,自己也能持有
??????? Person *p3 = [p2 retain];
??????? NSLog(@"%lu",p3.retainCount);? //2--->3
??????? [p2 release];//3-->2
??????? [p2 release];//2-->1
??????? [p3 release];//1-->0
???????
??????? Person *p4 = [[Person alloc]init];
??????? p4.name = @"小骨";
??????? [p4 retain];//2
??????? [p4 retain];//3
??????? [p4 retain];//4
??????? [p4 release];//3
??????? [p4 release];//2
??????? [p4 release];//1 ??????? [p4 release];//0 // ? ?? [p4 retain];//人死不能復生,對象死也不能復生 4、 方法的基本使用 ? ? ? ? 1.retain : 計算器 +1 ? ,會返回對象本身;(返回值為id泛類型) ? ? ? ?2.release : 計數器 - 1,沒有返回值 ? ? ? ? 3.retainCount 的作用:獲取當前對象的計數器數值 ? ? ? ??4.dealloc 當一個對象被銷毀的時候,系統會自動調用,再次方法中一定要調用[super delloc];且這句話要放到最后; 5、 概念 ? ?//僵尸對象:所占內存被回收的對象,就叫僵尸對象,僵尸對象不能再使用 ???????//野指針:指僵尸對象的指針就叫野指針 ??????? //空指針:沒有志向任何東西的指針就叫空指針叫空指針,(nil,NULL,0),給空指針發送消息
??????? // ? alloc 對應? dealloc ???????//? retain? 對應 release ? ? ? ? 區別: [[Person alloc]init]; ? 內存永遠不會被釋放 ??????? //??????? [[[Person alloc]init]release];? 創建的同時立即就被釋放掉 ???????//autorelease 相比 release,也能造成引用計數器-1,不過autorelease 不是立即-1,會在未來某段時間做-1操作; 6、 autorelease 執行實質,對一個對象使用autorelease 操作,這個對象的引用計數器不會立即減1,如果把這個autorelease? 操作放到自動釋放出中,會在出池子的一瞬間減1,如果你沒有放到池子中,不會對autorelease? 操作對象進行減1; ?注意:你要使用autorelease 必須和自動釋放池配合使用 //??????? Person *p5 = [[Person alloc]init];//0--->1 // ? ? ? ?p5.name = @"殺阡陌"; //??????? [p5 autorelease];//1 //??????? NSLog(@"%lu",p5.retainCount); ======================================================= 7、創建自動釋放池的兩種形式
???????//第一種形式 // ? ?NSAutoreleasePool? 自動釋放池類 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];
??????? Person *p6 = [[Person alloc]init];
??????? p6.name = @"白子畫";
??????? [p6 autorelease];//或者用[p6 release];
??????? NSLog(@"%lu",p6.retainCount);
??????? [pool release];
???????
??????? //第二種形式
??????? @autoreleasepool {
??????????? Person *p7 = [[Person alloc]init];
??????????? p7.name = @"糖寶";
??????????? [p7 autorelease];//未來的時間減1,出自動釋放池減1
//??????????? [p7 release];//-1 ??? //過度釋放
??????????? NSLog(@"%lu",p7.retainCount); ??? }//此時也會引起過度釋放,是由autorelease引起的 8、 內存管理的原則
??????? //水污染誰治理,誰alloc誰release,誰return誰release,autorelease
??????? //你想占用某個對象,就應該讓對象的計數+1,(也就是讓對象做以retain操作) ???????//當你不想持有(占有)某個對象時,就應該讓對象的引用計數-1,(也就是讓對象做一release操作) 重復使用的釋放可以設置帶有參數的宏定義,減少繁瑣的程序 #define kRelease_Safe(_point) [_point release];_point = nil; ??????? Person *p8 = [[Person alloc]init]; ??????? p8.name = @"紫熏"; ??????? Person *p9 = [p8 retain]; ? ? ? ?kRelease_Safe(p8); ??????? NSLog(@"%@",p9.name); ? ? ??kRelease_Safe(p9);? //??????? [p8 release];//對一個空指針發送消息,沒有任何影響 9、 NSMutableArray *mArray = [[NSMutableArray alloc]initWithCapacity:0];
??????? //向數組中添加十個人
??????? for (int i = 0; i < 10 ; i ++) {
??????????????? Person *person = [[Person alloc]init];
??????????????? person.name = [NSString? stringWithFormat:@"%d",i];
??????????????? //數組在添加元素的時候,會對添加的元素做一次retain操作
??????????????? [mArray addObject:person];
??????????????? kRelease_Safe(person); ??????? } ??????? NSLog(@"%@",mArray);
??????? //數組在釋放自己之前,會對之前添加到數組中的元素進行引用計數減1的操作 ???????kRelease_Safe(mArray); ??????? //此時我們沒有alloc 也沒有retain ,所以不需要對數組mArray2 的內存釋放負責
??????? NSMutableArray *mArray2 = [NSMutableArray array];//
??????? Person *p10 = [[Person alloc]init];
??????? p10.name = @"朱然";
??????? [mArray2 addObject:p10]; ???????kRelease_Safe(p10); ??????? NSString *string = [[NSString alloc]initWithString:@"12345678912345"]; ???????NSLog(@"%ld",string.retainCount); ?總結:非重點,但是考試一般會問及: 當使用stringWithFormat:創建的字符串對象當長度小于10的時候,在常量區;大于等于10的時候,在堆區;
????????? //使用其他方法創建的字符串都在常量區
??????? NSString *string2 = [NSString stringWithFormat:@"1234567890"]; ???????NSLog(@"%lu",string2.retainCount); ??????? //沒人去釋放字符串,stringWithFormat:? 計數器1,其他計數為-1; ====================================================== 10、 copy 對象能夠使用copy操作的前提是,此類必須遵循NSCopying 協議 ??????? //淺拷貝,只拷貝地址,同時對象的引用計數+1;此時拷貝出來的對象原對象的所占的空間大小相等,內容也相等 ???????//深拷貝 不止拷貝空間和內容,而且從新開辟了一塊內存 區別:淺拷貝會造成原對象的引用計數加+1,而深拷貝不會造成原對象的計數加+1; ? ? 例子:在Person類基礎上舉例 Person.h #import @interface Person : NSObject<</span>NSCopying>必須遵循NSCopying 協議 //名字的屬性 @property (nonatomic,copy)NSString *name; @end
Person.m - (void)dealloc{ ? NSLog(@"Person%@對象被銷毀了",_name); ??? [super dealloc]; } - (id)copyWithZone:(NSZone *)zone{
??? //返回對象的時候要做一次retain操作,外界的接受者才持有這個對象 ?? // return [self retain]; //深拷貝? 返回的是新的對象,此時兩個對象所占的空間大小相同,內容也相同
??? Person *p = [[Person allocWithZone:zone]init]; ??? p.name = self.name; ??? return p; } @end
main.m ? Person *p11 = [[Person alloc]init];
??????? p11.name = @"笙蕭默";
??????? Person *p12 = [p11 copy];
??????? NSLog(@"%@",p12.name); ???????NSLog(@"p11 = %p p12 = %p ",p11,p12); ? ? ? ??????? kRelease_Safe(p11); ???????kRelease_Safe(p12); ===================================================== 11、 new? 申請創建對象的同時讓其引用計數0-—>1(不常用) ??????? //new其實就做了alloc和init 兩步操作,申請空間并初始化
??????? //????? [Person new] = [Person alloc]init];
??????? Person *p13 = [Person new];
??????? p13.name = @"東方"; ???????kRelease_Safe(p13); 總結:內存管理的總結 ???????? 1.引用計數+1(alloc ,copy , new , retain)
???????? 2.引用計數 -1 (release , autorelease)
???????? 3.要想內存不出現泄漏,引用計數-1的次數相等
???????? 4.一旦引用計數為0的時候系統會自動調用dealloc 方法 ???????? 5.誰污染誰治理,誰alloc誰release,誰return誰release,autorelease 深入了解學習: http://blog.sina.com.cn/s/blog_814ecfa90102vuqv.html 歡迎學習本文,未經許可,不得私自轉載!
| 圖中那個的行為 | ? ? OC中操作 | OC中方法 |
| 根據照明設備所做的動作 | 對對象的操作 | |
| 開燈 ? | 生成對象 | alloc/copy/new |
| 需要照明 | 持有對象 | return |
| 不需要照明 | 釋放對象 | release/autorelese(不會立即釋放且與@autoreleasepool配合使用) |
| 關燈 | 廢棄對象 ? | dealloc |
??????? //圖中需要照明的人數,就代表引用計數
??????? //1.當第一人"需要照明",引用計數+1 ??? 有0-->1
??????? //2.當第二個人"需要照明",引用計數+1 ??? 有1-->2
??????? //3.當第二個人"需要照明",引用計數+1 ??? 有2-->3
??????? //4.當有一個人"不需要照明",引用計數-1 ??? 有3-->2
??????? //5.當再有一個人"不需要照明",引用計數-1 ??? 有2-->1 ???????//6.當再有一個人"不需要照明",引用計數-1 ??? 有1-->0 2、iOS平臺下適用計數器如何管理內存,有兩種方式 ? ??1.MRC:(Manual Reference Counting),手動引入計數器,有開發人員通過手動引入計數器來管理內存。 ? ? ? 2.ARC:(Automatic Reference Counting),自動引入計數器,由系統通過引入計數器管理內存 ???????//學習好MRC是為了更好使用ARC,iOS5.0之后就有了ARC; ARC和MRC的混編 ? ? ? ? 1.如果工程環境是ARC,而部分文件使用了MRC,使用一個參數???-fno-objc-arc ? ? ? ?2.如果工程環境是MRC,而部分文件使用了ARC,使用一個參數 ???-fobjc-arc ============================================================== 例子:? 1.自己創建的對象自己持有; Person.h @interface Person : NSObject //名字的屬性 @property (nonatomic,copy)NSString *name; @end
Person.m @implementation Person
//dealloc 方法是對象被銷毀的時候自動調用的方法,不需要手動調用,由于dealloc方法是重寫的父類,所以重寫此方法的時候,一定要把父類的方法內容也寫上 - (void)dealloc? ?{ ??NSLog(@"Person%@對象被銷毀了",_name);
???//以后重寫dealloc方法時一定調用[super dealloc];? 且此方法一定要寫在最下面 ??? [super dealloc]; } @end
main.m Person *p = [[Person alloc]init];//alloc會造成對象的引用計數器由0-->1 ??????? p.name = @"緩緩"; ??????? //如何判斷一個對象是否被持有,就看它的引用計數
??????? //retainCount :對象的引用計數 ???????NSLog(@"%lu",p.retainCount); //計數器為1 ??????? //如果自己創建的對象不使用時,釋放對象,使用release
??????? [p release];
// ??? NSLog(@"%lu",p.retainCount); ?????對象死了就不能再使用它了 // ??? [p release];??? 不要過度釋放,也等于操作僵尸對象 ?Person *p2 = [[Person alloc]init]; ? //0--->1 ??????? p2.name = @"武媚娘"; 3、retain可以讓對象的引用計數 +1
??????? //非自己創建的對象,自己也能持有
???????? p2 =? [p2 retain]; //由1--->2
??????? NSLog(@"%lu",p2.retainCount);
???????
????????//非自己創建的對象,自己也能持有
??????? Person *p3 = [p2 retain];
??????? NSLog(@"%lu",p3.retainCount);? //2--->3
??????? [p2 release];//3-->2
??????? [p2 release];//2-->1
??????? [p3 release];//1-->0
???????
??????? Person *p4 = [[Person alloc]init];
??????? p4.name = @"小骨";
??????? [p4 retain];//2
??????? [p4 retain];//3
??????? [p4 retain];//4
??????? [p4 release];//3
??????? [p4 release];//2
??????? [p4 release];//1 ??????? [p4 release];//0 // ? ?? [p4 retain];//人死不能復生,對象死也不能復生 4、 方法的基本使用 ? ? ? ? 1.retain : 計算器 +1 ? ,會返回對象本身;(返回值為id泛類型) ? ? ? ?2.release : 計數器 - 1,沒有返回值 ? ? ? ? 3.retainCount 的作用:獲取當前對象的計數器數值 ? ? ? ??4.dealloc 當一個對象被銷毀的時候,系統會自動調用,再次方法中一定要調用[super delloc];且這句話要放到最后; 5、 概念 ? ?//僵尸對象:所占內存被回收的對象,就叫僵尸對象,僵尸對象不能再使用 ???????//野指針:指僵尸對象的指針就叫野指針 ??????? //空指針:沒有志向任何東西的指針就叫空指針叫空指針,(nil,NULL,0),給空指針發送消息
??????? // ? alloc 對應? dealloc ???????//? retain? 對應 release ? ? ? ? 區別: [[Person alloc]init]; ? 內存永遠不會被釋放 ??????? //??????? [[[Person alloc]init]release];? 創建的同時立即就被釋放掉 ???????//autorelease 相比 release,也能造成引用計數器-1,不過autorelease 不是立即-1,會在未來某段時間做-1操作; 6、 autorelease 執行實質,對一個對象使用autorelease 操作,這個對象的引用計數器不會立即減1,如果把這個autorelease? 操作放到自動釋放出中,會在出池子的一瞬間減1,如果你沒有放到池子中,不會對autorelease? 操作對象進行減1; ?注意:你要使用autorelease 必須和自動釋放池配合使用 //??????? Person *p5 = [[Person alloc]init];//0--->1 // ? ? ? ?p5.name = @"殺阡陌"; //??????? [p5 autorelease];//1 //??????? NSLog(@"%lu",p5.retainCount); ======================================================= 7、創建自動釋放池的兩種形式
???????//第一種形式 // ? ?NSAutoreleasePool? 自動釋放池類 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];
??????? Person *p6 = [[Person alloc]init];
??????? p6.name = @"白子畫";
??????? [p6 autorelease];//或者用[p6 release];
??????? NSLog(@"%lu",p6.retainCount);
??????? [pool release];
???????
??????? //第二種形式
??????? @autoreleasepool {
??????????? Person *p7 = [[Person alloc]init];
??????????? p7.name = @"糖寶";
??????????? [p7 autorelease];//未來的時間減1,出自動釋放池減1
//??????????? [p7 release];//-1 ??? //過度釋放
??????????? NSLog(@"%lu",p7.retainCount); ??? }//此時也會引起過度釋放,是由autorelease引起的 8、 內存管理的原則
??????? //水污染誰治理,誰alloc誰release,誰return誰release,autorelease
??????? //你想占用某個對象,就應該讓對象的計數+1,(也就是讓對象做以retain操作) ???????//當你不想持有(占有)某個對象時,就應該讓對象的引用計數-1,(也就是讓對象做一release操作) 重復使用的釋放可以設置帶有參數的宏定義,減少繁瑣的程序 #define kRelease_Safe(_point) [_point release];_point = nil; ??????? Person *p8 = [[Person alloc]init]; ??????? p8.name = @"紫熏"; ??????? Person *p9 = [p8 retain]; ? ? ? ?kRelease_Safe(p8); ??????? NSLog(@"%@",p9.name); ? ? ??kRelease_Safe(p9);? //??????? [p8 release];//對一個空指針發送消息,沒有任何影響 9、 NSMutableArray *mArray = [[NSMutableArray alloc]initWithCapacity:0];
??????? //向數組中添加十個人
??????? for (int i = 0; i < 10 ; i ++) {
??????????????? Person *person = [[Person alloc]init];
??????????????? person.name = [NSString? stringWithFormat:@"%d",i];
??????????????? //數組在添加元素的時候,會對添加的元素做一次retain操作
??????????????? [mArray addObject:person];
??????????????? kRelease_Safe(person); ??????? } ??????? NSLog(@"%@",mArray);
??????? //數組在釋放自己之前,會對之前添加到數組中的元素進行引用計數減1的操作 ???????kRelease_Safe(mArray); ??????? //此時我們沒有alloc 也沒有retain ,所以不需要對數組mArray2 的內存釋放負責
??????? NSMutableArray *mArray2 = [NSMutableArray array];//
??????? Person *p10 = [[Person alloc]init];
??????? p10.name = @"朱然";
??????? [mArray2 addObject:p10]; ???????kRelease_Safe(p10); ??????? NSString *string = [[NSString alloc]initWithString:@"12345678912345"]; ???????NSLog(@"%ld",string.retainCount); ?總結:非重點,但是考試一般會問及: 當使用stringWithFormat:創建的字符串對象當長度小于10的時候,在常量區;大于等于10的時候,在堆區;
????????? //使用其他方法創建的字符串都在常量區
??????? NSString *string2 = [NSString stringWithFormat:@"1234567890"]; ???????NSLog(@"%lu",string2.retainCount); ??????? //沒人去釋放字符串,stringWithFormat:? 計數器1,其他計數為-1; ====================================================== 10、 copy 對象能夠使用copy操作的前提是,此類必須遵循NSCopying 協議 ??????? //淺拷貝,只拷貝地址,同時對象的引用計數+1;此時拷貝出來的對象原對象的所占的空間大小相等,內容也相等 ???????//深拷貝 不止拷貝空間和內容,而且從新開辟了一塊內存 區別:淺拷貝會造成原對象的引用計數加+1,而深拷貝不會造成原對象的計數加+1; ? ? 例子:在Person類基礎上舉例 Person.h #import @interface Person : NSObject<</span>NSCopying>必須遵循NSCopying 協議 //名字的屬性 @property (nonatomic,copy)NSString *name; @end
Person.m - (void)dealloc{ ? NSLog(@"Person%@對象被銷毀了",_name); ??? [super dealloc]; } - (id)copyWithZone:(NSZone *)zone{
??? //返回對象的時候要做一次retain操作,外界的接受者才持有這個對象 ?? // return [self retain]; //深拷貝? 返回的是新的對象,此時兩個對象所占的空間大小相同,內容也相同
??? Person *p = [[Person allocWithZone:zone]init]; ??? p.name = self.name; ??? return p; } @end
main.m ? Person *p11 = [[Person alloc]init];
??????? p11.name = @"笙蕭默";
??????? Person *p12 = [p11 copy];
??????? NSLog(@"%@",p12.name); ???????NSLog(@"p11 = %p p12 = %p ",p11,p12); ? ? ? ??????? kRelease_Safe(p11); ???????kRelease_Safe(p12); ===================================================== 11、 new? 申請創建對象的同時讓其引用計數0-—>1(不常用) ??????? //new其實就做了alloc和init 兩步操作,申請空間并初始化
??????? //????? [Person new] = [Person alloc]init];
??????? Person *p13 = [Person new];
??????? p13.name = @"東方"; ???????kRelease_Safe(p13); 總結:內存管理的總結 ???????? 1.引用計數+1(alloc ,copy , new , retain)
???????? 2.引用計數 -1 (release , autorelease)
???????? 3.要想內存不出現泄漏,引用計數-1的次數相等
???????? 4.一旦引用計數為0的時候系統會自動調用dealloc 方法 ???????? 5.誰污染誰治理,誰alloc誰release,誰return誰release,autorelease 深入了解學習: http://blog.sina.com.cn/s/blog_814ecfa90102vuqv.html 歡迎學習本文,未經許可,不得私自轉載!
總結
以上是生活随笔為你收集整理的内存管理Memoryamp;nbsp;OC——第九天的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: “听我说谢谢你”还能用古诗来说?清华搞了
- 下一篇: Web身份验证(WebAuthn)