推 johnlinvc:書有點舊了,三年前確實一定要打@synthesize 02/11 16:40
→ HuangJC:原來如此.. 真有 02/11 16:46
→ HuangJC:我快被 ARC 搞死了,這東西好像挺新.. 02/11 16:46
→ HuangJC:這本書就沒教 ARC (應該沒教吧) 02/11 16:47
推 johnlinvc:書裡面如果還有retain 關鍵字的話就可以當古文物了XD 02/11 16:56
→ HuangJC:那我去加瑪雅人好友好了 Orz 02/11 16:57
順便討論一下 gc
對於自動 reference count 的作法
其實我從 VC++ / MFC 轉過來,並不陌生
首先是 CString 物件,它就是自動管理記憶體
當無人 reference 它時,才釋放
接下來是 COM,雖然我 COM 始終學不好
只好模仿它做一些類似的 class
但教導 COM 的書裏就有完整介紹 reference count
其實 CString 也是用這概念
大致上,有人引用就 ref + 1
失去引用就 ref - 1
這點,並沒由 C++ 直接支援
而是由改寫一堆 operater function 達成
(比如 CString a = str
這樣會使 str 計數加一,那可能是改寫 constructor,可能是改寫 operator =
總之要改寫的點很多,但繁複的改寫後就可以打造出 reference count)
COM MODEL 比較方便的是,繼承就擁有這些
如果不用COM,也可以經由 template 來打造自己的 class
(同樣的我也沒學好,所以我無法弄出自己的自動記憶體管理物件;
都是半調子,可能只在 destructor 管理一下)
學到 Android/java 時,挺開心的,有 gc
對物件的理解是, 它是語言直接支援 reference count
但為什麼要跟我說, gc 是有一個獨立的 thread 在做呢?
如果有 refernce count,那就在 count 歸零時釋放就好
不必另一個 thread 啊..
然後現在到 Object C, 又跟我說它的 ARC 是由 compiler 實作
走 reference count!! 不必再一個 thread
(但也因此限制了我某些用法,我還搞不懂為何被限制)
我已經混亂了啊~~~
※ 編輯: HuangJC 來自: 60.251.197.63 (02/11 17:07)
推 johnlinvc:java的不是ref count, 他是跑generation GC 02/11 17:36
→ johnlinvc:也就是直接從object root去traverse,砍了走不到的 02/11 17:38
→ johnlinvc:generation指的是有分粗略GC和仔細GC,用來加快速度 02/11 17:39
→ HuangJC:喔,因為所有物伴有同一個根部 class,這變得不難理解!! 02/11 18:28
→ HuangJC:那我如果又有幸回到 C++,我寫這個就好了,安全又省事 XD 02/11 18:29
→ atst2:arc跟gc不同,不要搞混了. reference count也跟gc不同 02/11 18:54
→ atst2:學究一點的講法,rc/gc是記憶體以及所有權管理的不同策略 02/11 18:56
→ atst2:想要達到的目的類似, 但做法不同. arc則是自動化的rc 02/11 18:56
我可以這樣說嗎?
CString, COM
都是有寫好的函式庫, frame work
它所用的 C++ 語法仍然是標準的;它沒有擴充或改寫 C++
它只是要預先引入函式庫而已
那這算 rc
→ atst2:是由編譯器用前置處理器自動幫你加上retain/release 02/11 18:57
目前我只知道 C 的這種前置處理器
它要自己寫想去替換什麼,或者 #if #else, 也不過是協助 user 去實現 code 管理
有更廣義的前置處理器嗎? 或就指用這個?
其實要怎麼說它是前置處理器呢?
C 的那個很明確,因為被 #if #else 框出去不用的 code
就保障百分百不會影響流程,不會影響 code size
完全和執行期無關,也完全和後期 compile time 無關了
這在我們修改過於巨大,不明來源,前輩留下的 source code 時很有用
因為我保證是我幹的就我幹的,我沒幹的也保證不會影響別人
可以百分百沒有 side effect
當專案進行中,已經有產品 release 又要改 code
主管只接受這種修改
可以說,用一個全域布林變數
if ( bNew )
newcode();
else
oldcode();
這樣,雖然也漂亮,但主管就不接受了
因為多一個 byte 就不知會不會影響堆疊,根本不想冒險
那麼 ARC 是怎麼加,所謂前置處理器加的
我實在想見識見識
或者它不是 C 的那種前置處理器,是更廣義的?
謝謝
※ 編輯: HuangJC 來自: 60.251.197.63 (02/11 19:30)
→ atst2:在編譯前處理, 就算前置處理器了. 跟C的差異只在處理的目的 02/11 20:19
→ atst2:不同. 詳情可以參考一下wiki對preprocessor的說明. 02/11 20:19
→ atst2:arc簡單說就是剖析你的程式, 判斷在那些地方應該要加上 02/11 20:20
→ atst2:retain,release等字串. 加完字串後,還是交給objective-c的 02/11 20:21
→ atst2:編譯器來處理. 02/11 20:21
-----
推 johnlinvc:java的不是ref count, 他是跑generation GC 02/11 17:36
→ johnlinvc:也就是直接從object root去traverse,砍了走不到的 02/11 17:38
本來想說在 C++ 以後也可以自己寫這種邏輯
昨天突然發現我寫不出來
class C1 : RootClass{
}
C1 I1 = new C1();
像這樣, RootClass 裏要有什麼?
我可以在 C1 的 constructor 去註冊它自己
方法也不用自己寫,從 RootClass 繼承就好
class RootClass {
RootClass() {
Register(this); // 就簡單把 this 指標存入一個 list 裏就好
}
}
所以以後從 RootClass 裏就可以搜尋到所有物件
但我要怎麼知道某物件沒有人參考到它了?
I1 = null;
像這行就代表 I1 不再使用原物件,原物件可以刪除了
除非我 traverse 的方式不只尋找所有物件,還有尋找所有變數
比如維護兩個 list,
list1 裏面是物件,如上例中的 C1 物件
list2 裏面是變數,如上例中的 I1
一開始 I1 = C1, 所以 list1 中的物件有被使用到
後來 I1 = null, 所以把 list2 中的物件都繞完後,
發現 list1 裏有物件沒人使用了,刪除
這樣似乎可行,問題是我怎麼取得 &I1,這豈不是要在產生變時數馬上去註冊它
C1 I1 = new C1();
Register(&I1);
這種麻煩事還要自己做,而無法寫在 RootClass 內變成 transparent
那豈不是說一定要 compiler 支援?
因為 compiler 才知道我何時又要求一個變數了,何時變數從堆疊彈出了
(退出函式時, 變數 I1 的生命週期結束,雖然沒有 I1 = null 這句, 但一樣可以刪除了)
user 自己寫總是會漏勾的
與其如此,看到 CString 的記憶體管理那麼完整,使用時可以忘了它的存在
我覺得還是補上一些 method,內建 reference count 簡單多了
※ 編輯: HuangJC 來自: 60.251.197.63 (02/13 12:56)
※ 編輯: HuangJC 來自: 60.251.197.63 (02/13 19:46)