對於C++中的廢料收集,在這裡我下了很多的功夫進行學習研究,在這裡把我自己對C++中的廢料收集總結出的經驗在這裡跟大家學習研究,它是一種機制,能夠簡化設計、排除掉許多產生錯誤的根源。
在本文中,我並不想揭露Java提供的廢料收集機制的天生缺陷,而是指出了C++中引入廢料收集的可行性。請讀者注意,這裡介紹的方法更多的是基於當前標准和庫設計的角度,而不是要求修改語言定義或者擴展編譯器。
什麼是廢料收集?
作為支持指針的編程語言,C++將動態管理存儲器資源的便利性交給了程序員。在使用指針形式的對象時(請注意,由於引用在初始化後不能更改引用目標的語言機制的限制,多態性應用大多數情況下依賴於指針進行),程序員必須自己完成存儲器的分配、使用和釋放,語言本身在此過程中不能提供任何幫助,也許除了按照你的要求正確的和操作系統親密合作,完成實際的存儲器管理。標准文本中,多次提到了“未定義(undefined)”,而這大多數情況下和指針相關。
某些語言提供了廢料收集機制,也就是說程序員僅負責分配存儲器和使用,而由語言本身負責釋放不再使用的存儲器,這樣程序員就從討厭的存儲器管理的工作中脫身了。然而C++並沒有提供類似的機制,C++的設計者Bjarne Stroustrup在我所知的唯一一本介紹語言設計的思想和哲學的著作《The Design and Evolution of C++》(中譯本:C++語言的設計和演化)中花了一個小節討論這個特性。簡而言之,Bjarne本人認為。
“我有意這樣設計C++,使它不依賴於自動廢料收集(通常就直接說廢料收集)。這是基於自己對廢料收集系統的經驗,我很害怕那種嚴重的空間和時間開銷,也害怕由於實現和移植廢料收集系統而帶來的復雜性。還有,廢料收集將使C++不適合做許多底層的工作,而這卻正是它的一個設計目標。但我喜歡C++中的廢料收集收集的思想,它是一種機制,能夠簡化設計、排除掉許多產生錯誤的根源。
需要廢料收集的基本理由是很容易理解的:用戶的使用方便以及比用戶提供的存儲管理模式更可靠。而反對廢料收集的理由也有很多,但都不是最根本的,而是關於實現和效率方面的。
已經有充分多的論據可以反駁:每個應用在有了廢料收集之後會做的更好些。類似的,也有充分的論據可以反對:沒有應用可能因為有了廢料收集而做得更好。並不是每個程序都需要永遠無休止的運行下去;並不是所有的代碼都是基礎性的庫代碼;
對於許多應用而言,出現一點存儲流失是可以接受的;許多應用可以管理自己的存儲,而不需要廢料收集或者其他與之相關的技術,如引用計數等。我的結論是,從原則上和可行性上說,廢料收集都是需要的。但是對今天的用戶以及普遍的使用和硬件而言,我們還無法承受將C++的語義和它的基本庫定義在廢料收集系統之上的負擔。”
以我之見,統一的自動廢料收集系統無法適用於各種不同的應用環境,而又不至於導致實現上的負擔。稍後我將設計一個針對特定類型的可選的廢料收集器,可以很明顯地看到,或多或少總是存在一些效率上的開銷,如果強迫C++用戶必須接受這一點,也許是不可取的。
關於為什麼C++沒有廢料收集以及可能的在C++中為此做出的努力,上面提到的著作是我所看過的對這個問題敘述的最全面的,盡管只有短短的一個小節的內容,但是已經涵蓋了很多內容,這正是Bjarne著作的一貫特點,言簡意赅而內韻十足。
下面一步一步地向大家介紹我自己土制佳釀的廢料收集系統,可以按照需要自由選用,而不影響其他代碼,C++中提供的構造函數和析構函數很好的解決了自動釋放資源的需求。Bjarne有一句名言,“資源需求就是初始化(Resource Inquirment Is Initialization)”。
因此,我們可以將需要分配的資源在構造函數中申請完成,而在析構函數中釋放已經分配的資源,只要對象的生存期結束,C++中的廢料收集對象請求分配的資源即被自動釋放。那麼就僅剩下一個問題了,如果對象本身是在自由存儲區(Free Store,也就是所謂的“堆”)中動態創建的,並由指針管理(相信你已經知道為什麼了),則還是必須通過編碼顯式的調用析構函數,當然是借助指針的delete表達式。