Allocator(概念)是對訪問、尋址、分配、釋放、構造和析構策略的封裝。是一個知足特定要求的類。標準庫中須要分配釋放存儲空間的容器都須要一個Allocator,除了std::array。函數
Allocator 須要知足的條件有不少,可是大部分都是可選的,只有幾個必須存在的成員。spa
對於表達式Alloc a2 = a1; Alloc a2(a1) 要求執行完畢後a2 == a1,不可拋出異常指針
對於表達式Alloc a2 = std::move(a1); Alloc a2(std::move(a1)); 使用a1構造a2,a2應等於a1的先前值。(C++17 起要求a1的值在構造後不發生改變,而且a1 == a2。)code
標準沒有聲明他們的存在,可是顯然他們應該和上面的構造語義相同。對象
用於map等分配的實際類型不是你傳入的allocator的value_type的狀況。內存
對於表達式 AllocA a(b),其中b是由AllocA::template rebind得到的類型AllocB的實例,構造a,使得AllocB(a) == b, b == AllocA(a)。ci
對於表達式 AllocA a(b),其中b是由AllocA::template rebind得到的類型AllocB的實例,構造a,使得a == 以前的 AllocA(b)get
其它的可選設施能夠在這一頁找到,是否實現由 Allocator 的實現邏輯決定 http://en.cppreference.com/w/cpp/concept/Allocatorit
標準推薦經過 std::allocator_traits<Allocator> 來調用 Allocator 的各類方法,及獲取其餘類型,這個 trait 類提供了 Allocator 中可選成員的默認實現。io
size_type
若是你不想使用默認的std::size_t,能夠用這個來自定義size_type類型,固然對應的allocate和deallocate方法的size參數也應該變成這個類型
rebind用來從已有的allocator類型獲取一個新的用來分配另外一個類型U的allocator類型
注意,rebind只對有模板參數的allocator可選
allocator_traits的默認實現是用U來替換當前類型的第一個模板參數
分配足夠容納n個對象的連續空間,ptr用做一個hint(好比在ptr地址附近尋找可用內存,用來保持局部性)
獲取可分配的最大對象數目
allocator_traits會提供一個返回(size_t)-1的實現(或者(size_t)-1 / sizeof(T),since C++17)
在標準庫容器拷貝構造時,由構造函數調用,向源allocator獲取一個用來構造新容器的allocator的實例
allocator_traits會提供一個直接返回源容器的allocator自己的實現
在構造函數不可以知足allocator的邏輯需求時定義這個函數
在給定指針指向的內存上構造對象,須要注意的是,ptr指向的對象類型不必定是allocator的value_type,這個函數有必要作成模板的
在須要自定義對象構造行爲時定義它,好比打個log,try_catch一下什麼的
析構ptr指向的對象,須要注意的是,ptr指向的對象類型也不必定是value_type,這個函數有必要作成模板的
allocator的相等比較的意義是,一個allocator分配的空間,是否能夠用另一個allocator來釋放,is_always_equal旨在儘量消除運行期的比較
std::allocator就是always_equal的,由於他們都是new和delete的封裝,一個std::allocator new的固然能夠用另外一個std::allocator來delete
allocator_traits的默認實現是,當你的allocator是空類,那麼爲true_type
此三個類型標記了在容器進行拷貝賦值、移動賦值或交換的時候,allocator是否須要進行對應操做。
容器在進行拷貝賦值、移動賦值和交換時的邏輯,應該考慮到以上成員和allocator的相等性
在兩個容器拷貝賦值時(container1 = container2)
propagate…copy… |
兩個allocator是否相等 |
拷貝賦值行爲 |
true |
true |
拷貝allocator,拷貝container2全部元素 |
true |
false |
析構container1全部元素並釋放空間,拷貝allocator,拷貝container2元素 |
false |
true |
不拷貝allocator,拷貝container2全部元素 |
false |
false |
不拷貝allocator,拷貝container2全部元素 |
在兩個容器移動賦值時(container1 = std::move(container2))
propagate…move… |
兩個allocator是否相等 |
移動賦值行爲 |
true |
true |
析構container1全部元素並釋放空間,移動allocator,接管container2的內部指針 |
true |
false |
析構container1全部元素並釋放空間,移動allocator,接管container2的內部指針 |
false |
true |
析構container1全部元素並釋放空間,不移動allocator,接管container2的內部指針 |
false |
false |
析構container1全部元素,不釋放空間,不移動allocator,分配足夠裝下container2全部元素的空間,將container2的元素盡數移動過來 |
在兩個容器交換時,沒有更多問題,僅需視propagate_on_container_swap值,交換allocator便可。但須要注意的是,若是allocator不可交換,而且不相等,那麼容器交換是UB。
固然以上只是標準容器的實現,你的容器大能夠沒必要如此麻煩。