深度剖析空間配置器(一)構造和析構函式

2021-07-30 19:00:40 字數 2688 閱讀 2764

頻繁的申請和釋放,就會頻繁的呼叫malloc函式和free函式

呼叫函式會壓棧出棧,這些都是有開銷的

這就會造成,即使是有足夠的記憶體(40位元組),但是通過申請並不能得到乙個連續24位元組的記憶體

從而引入了空間配置器

空間介面卡是stl,標準模板庫的六大元件之一,其餘分別是:容器,迭代器,演算法,配接器,仿函式

主要分三個檔案實現,首先我們來介紹第乙個檔案stl_construct.h  這裡定義了全域性函式construct()和destroy(),負責物件的構造和析構。

#include //定位new 的標頭檔案

template inline void _construct(_t1* __p, const _t2& __value)

template inline void _construct(_t1* __p)

template inline void construct(_t1* __p, const _t2& __value) 

template inline void construct(_t1* __p)

placement new 允許你在乙個已經分配好的記憶體中(棧或堆)構造乙個新的物件,原型中 (void*) __p 實際上就是指向乙個已經分配好的記憶體緩衝區的首位址。stl 借助c++中的 placement new 來提高效率,因為使用 new 操作符分配記憶體需要在堆中查詢足夠大的剩餘空間,這個操作速度是很慢的,而且有可能出現無法分配記憶體的異常。借助 placement new 就可以解決這個問題,我們構造物件都是在乙個預先準備好了的記憶體緩衝區中進行,不需要查詢記憶體,記憶體分配的時間是常數,而且不會出現在程式執行中途出現記憶體不足的異常。

//單個物件

template inline void _destroy(_tp* __pointer)

//迭代器版本

template void

__destroy_aux(_forwarditerator __first, _forwarditerator __last, __false_type)//物件的析構函式不是無意義的,函式內部呼叫destroy()

template inline void __destroy_aux(_forwarditerator, _forwarditerator, __true_type) {} //物件的析構函式是無意義的,什麼都不做。

//這個函式判斷物件的析構函式是否是 無意義的。

template inline void

__destroy(_forwarditerator __first, _forwarditerator __last, _tp*)

//這個函式判斷迭代器所指向的物件的型別的指標。

template inline void _destroy(_forwarditerator __first, _forwarditerator __last)

//迭代器版本 destroy()_destroy() -> __destroy() -> __destroy_aux() -> destroy() 指標版本

//所以實際上是逐個析構,只是中間為了效率,引入了判斷元素的指標型別,來確定物件是否具備有用的析構函式

template inline void destroy(_tp* __pointer) 

template inline void destroy(_forwarditerator __first, _forwarditerator __last)

上面可以看出,對於迭代器版本的destroy() 實際最後都落腳到了單一物件指標版本的 destroy()。那麼為什麼要繞一大圈呢?因為這裡接受的引數是兩個迭代器,目的就是將這兩個迭代器範圍內的所有物件都析構掉,如果範圍很大,並且物件的析構函式都是無關緊要的,那麼一次次的呼叫這些個無用的析構函式,勢必會對效率產生大的影響,所以先利用__value_type(__first) 獲得迭代器所指物件的型別的指標,再利用 __type_traits<_tp> 判斷該型別的析構函式是否是無意義的,如果是則什麼也不做,如果不是則迴圈逐個析構範圍內的物件。

所以物件的構造實際是通過 placement new 完成的(快取提前分配然後進行物件的分配);物件的析構則通過呼叫外在物件的析構函式(~_tp())。注意的是,這裡的析構只是析構物件,分配好的快取並沒有釋放,所以可以反覆利用快取並給它分配物件。不打算再次使用這個快取時,你可以delete 將其釋放掉。

另外stl(v3.3)版本destroy() 還針對迭代器型別為定義了特化版本

inline void _destroy(char*, char*) {}

inline void _destroy(int*, int*) {}

inline void _destroy(long*, long*) {}

inline void _destroy(float*, float*) {}

inline void _destroy(double*, double*) {}

inline void _destroy(wchar_t*, wchar_t*) {}

swift構造器和析構器

1.構造器重載 函式有相同的名字 引數列表不同或返回值型別不同,或外部引數名不同 橫向 類似於值型別構造器 發生在同一類內部,這種構造器稱為便利構造器 在構造器前面加上了convenience關鍵字 向上 發生在繼承情況下,在子類構造過程中要先呼叫父類構造器,初始化父類的儲存屬性,這種構造器稱為指定...

c 構造器和析構器

c 構造器和析構器主要負責構建物件和銷毀物件,在物件作用域結束後,銷毀物件。一般來說,建構函式用來完成事先的初始化和準備工作 申請分配記憶體 析構函式用來完成事後所必須的清理工作 清理記憶體 初始建構函式之建構函式特性 構造器名與類名一樣 定義 car void 呼叫 car car void 析構...

深度剖析C 全域性建構函式和析構函式的呼叫機制

c 全域性建構函式和析構函式的呼叫機制 控制台exe中c 的全域性變數在main之前初始化,在main之後清除,vc編譯器 鏈結器和vc執行庫 互相配合完成了這個魔術。請複製這段 到你新建的控制台程式,建立並執行 include stdafx.h include define secname crt...