3 簡單的空間配置器
本項目GitHub: HuangCheng72/HCSTL: 我的STL實現(xiàn) (github.com): https://github.com/HuangCheng72/HCSTL
進(jìn)入正文。
我們在上一篇中留下了一個問題還沒有解決,就是T為non-POD類型的時候,不能delete回收內(nèi)存空間的問題。這里不對問題的來龍去脈作過多回顧,需要回顧請看上一篇。
我們在上一篇中提到,我們new一個類的對象,涉及了兩個操作:
申請一塊內(nèi)存空間,用來存放這個對象。
在這塊空間上根據(jù)參數(shù)輸入調(diào)用類相應(yīng)的構(gòu)造函數(shù),創(chuàng)建這個對象(初始化內(nèi)存空間的各個參數(shù))。
而T為POD類型的時候,只需要進(jìn)行1的操作,申請內(nèi)存空間,就可以存放數(shù)據(jù)了。
在上一篇中,我們構(gòu)造對象使用的是定位new(placement new),在網(wǎng)上查資料發(fā)現(xiàn)定位new運算符的一個特點是,它能在堆和棧上創(chuàng)建對象,而我們知道普通的new和delete是從堆上創(chuàng)建對象和回收內(nèi)存到堆上的,因此定位new使用之后是不可以使用普通的delete去回收空間(誰知道你是不是在棧上創(chuàng)建的),只能顯式調(diào)用對象析構(gòu)函數(shù)來空出內(nèi)存空間。這也解決了我們之前的一大疑惑。而普通的new申請出來的內(nèi)存空間只能由普通的delete回收。
所以我們可以換個思路,分離這兩個操作,我們只從堆上申請內(nèi)存,也只回收到堆上,然后在申請到的內(nèi)存上創(chuàng)建對象,對象析構(gòu)之后再回收到堆上。這樣不就能解決我們的non-POD類型的內(nèi)存無法回收造成浪費的問題了。
C++提供了兩個全局函數(shù) ::operator new() 和 ::operator delete() ,這兩個函數(shù)是對C語言 malloc 和 free 的封裝,起到的效果是一樣的。
所以我們修改vector中的輔助函數(shù)和兩個帶參構(gòu)造器以及析構(gòu)器:
run一下,順利運行。
因為STL不可能只有一個vector容器需要內(nèi)存管理,而且這么實現(xiàn)代碼可讀性也比較差。為了提高代碼的復(fù)用性和可讀性,我們可以考慮分離出一個專門的組件,負(fù)責(zé)內(nèi)存的管理(目前只有申請和釋放)和對象的構(gòu)造和析構(gòu)。這就是STL六大組件中的空間配置器(allocator)。
目前,我們先實現(xiàn)一個最簡單的空間配置器,空間配置部分簡單封裝 ::operator new 和 ::operator delete 即可,對象構(gòu)造則是簡單封裝定位new,析構(gòu)則是簡單調(diào)用類的析構(gòu)器即可。
請建立兩個頭文件,allocator.h 和 constructor.h,分別實現(xiàn)兩個部分。
allocator.h:
constructor.h:
以該空間配置器為基礎(chǔ),同時為了提高代碼的可讀性,vector的實現(xiàn)如下:
main.cpp的簡單測試:
順利運行。
歡迎訪問本項目的GitHub倉庫,如果對您有幫助,麻煩給項目一個star,謝謝!
HuangCheng72/HCSTL: 我的STL實現(xiàn) (github.com): https://github.com/HuangCheng72/HCSTL