OC 第十章 屬性的內部實現原理

2021-07-08 21:51:36 字數 4280 閱讀 8909

//                  第十章 屬性的實現原理

// 引用計數: (retaincount) 指向同一塊記憶體的引用個數; 仍然需要release

// 1.引用計數只對堆區的物件有意義,每個物件都有引用計數

// 1)字串引用計數問題

// 情況1:常量區

nsstring *str = @"程式設計師";

nslog(@"%@ %lu", str, str.retaincount);//列印結果:18446744073709551615

//%lu溢位,列印出很大的書,說明是個負數, 用 %d 列印

nslog(@"%@, %d", str, str.retaincount);//列印結果:-1

// 情況2:常量區

nsstring *str1 = [nsstring alloc]initwithstring:@"產品狗"];

nslog(@"%@ %lu", str1, str1.retaincount);

// 情況3:堆區

nsstring *str2 = [[nsstring alloc]initwithformat:@"架構獅"];

nslog(@"%@ %lu", str2, str2.retaincount);

//注: 當[[nsstring alloc]initwithformat:@"架構獅"];中字串為中文, retaincount ++; 若為中文或數字 10 個以內為 - 1, 之後為 1;

// 2)setter和getter方法 屬性的內部實現

// assign:

// 內部實現:

@synthesize age = _age;

//非物件型別 直接寫

-(void)setage:(nsinteger)age

-(nsinteger)age

// copy、retain:

// (1)(setter): 釋放例項變數上一次的retain, 為這次賦值retain

// (上次為0則retaincount ++, 否則不變)

// (2)(getter): 幫別人retain, 自動釋放(retaincount ++)

// 情況1:setter方法的野指標異常

// 原理:

person *per = [[person alloc]init];

per.name = [str1 retain];//不加retain, 訪問per.name會奔潰

per.name = [str2 retain];//每一次給屬性命名, 都要加上retain; 因此需要在屬性內部加上 retain

[str2 release];

nslog(@"%@", per.name);

[per.name release];

[per release];

[per sayhello];//給乙個已經被alloc的物件發訊息, 會造成crash

nslog(@"%lu", per.retaincount);

// setter方法的內部實現

@synthesize name = _name;

-(void)setname:(nsstring *)name

}// 情況2: getter方法的野指標異常

// 原理:

nsstring *str3 = @"小笨豬";

person *per3 = [[person alloc]init];

per3.name = str3;//此時per3.name指向str3

[str3 release];//str3釋放

nsstring *str4 = per.name;//此時如果str被釋放, 會造成crash

[per3 release];

nslog(@"%@", str4);

// 2.物件定義的記憶體管理: 被賦值的例項變數retaincount++

// 1)便利構造器:

// 原理:

nsarray *arr = [nsarray arraywithobjects:@"2", @"3", @"4", nil];

nslog(@"%lu", arr.retaincount);//arr的引用計數

[arr release];

// 內部實現:

+(instancetype)personwithname:(nsstring *)name

// 2)初始化:

// 原理:

nsstring *str = [[nsstring alloc]initwithstring:@"產品狗"];

person *per = [[person alloc]initwithname:str age:23];//在這裡面需要_name retain

per.name = @"cto";//這裡會使引用計數變為 -1

nslog(@"str 的引用計數: %lu", str.retaincount);//str的引用計數為3

nslog(@"per.name 的引用計數: %lu", per.name

.retaincount);的引用計數也為3, 因為它們指向同一塊記憶體空間

// 內部實現:

-(instancetype)initwtihname:(nsstring *)name age:(nsinteger)age

return

self;

}// 例子1:分析列印結果: str的引用計數:1 per.name的引用計數:3

nsstring *str = [[nsstring alloc]initwithformat:@"產品狗"];

person *per = [[person alloc]initwtihname:str age:23];

per.name = [[nsstring alloc]initwithformat:@"逗比"];//先釋放使str.retaincount --

nslog(@"str 的引用計數: %lu", str.retaincount);

nslog(@"per.name 的引用計數: %lu", per.name

.retaincount);

// 例子2:分析列印結果: 1 , - 1 , -1

nsstring * astring = [[nsstring alloc] initwithformat:@"程式設計師"];

nslog(@"%d",astring.retaincount);

astring = @"456";

nslog(@"%d",astring.retaincount);

[astring release];

astring = @"789";

nslog(@"%d",astring.retaincount);

// 3)集合的記憶體管理: 陣列、集合、字典:

person *per = [[person alloc]init];

person *per1 = [[person alloc]init];

person *per2 = [[person alloc]init];

nslog(@"%lu", per.retaincount);//引用計數為1

nsmutablearray *arr = [[nsmutablearray alloc]initwithobjects:per, per1, per2, nil];//物件新增到陣列中的時候,引用計數 +1

nslog(@"%lu", per.retaincount);//引用計數為2

[per release];

nslog(@"%@", arr[0]);

[arr removeobject:per];//將物件從陣列中移除的時候, 引用計數減1

nslog(@"%lu",per.retaincount);

[arr release];//陣列中被(dealloc)釋放的時候, 陣列中的每個元素引用計數減1

nslog(@"%lu",per2.retaincount);

// 4)類的**

// 內部實現:

-(void)dealloc

打下手 -> 程式設計師 -> teemo隊長 -> 專案經理 -> 架構師 -> cto

第十章 屬性

z屬性 本章也比較簡單稍作介紹 無參屬性就是我們常見的屬性 可以封裝屬性 以執行緒安全方式訪問 有參屬性就是c 中的所引器 匿名型別 如圖遇到如下 具體點就是 上面的注釋也已經講清楚了,定義的型別之後,構造例項,然後初始化屬性。現在詳細說下 編譯器接收到 上圖 先用var 定義乙個型別,但是不具體指...

第十章 屬性

目錄 10.1 無參屬性 10.2 有參屬性 10.3 呼叫屬性訪問器方法時的效能 10.4 屬性訪問器的可訪問性 10.5 泛型屬性訪問器方法 物件導向設計和程式設計的重要原則之一就是資料封裝,意味著型別的字段不應該公開,否則很容易因為不恰單使用欄位而破壞物件的狀態。可將屬性想象成智慧型字段,即背...

第十章 多型 內部類

10.1 多型概述 多型是指乙個物件對應不同型別的引用,體現為父類或介面指向子類物件。cat c new cat 正常 animal a new cat 多型多型的使用提高了 的可擴充套件性。10.2 弊端 前提 弊端 只能呼叫父類成員方法 前提 兩者為繼承或實現關係,並且有覆蓋的功能 10.3 多...