C++ Boost Pool超詳細(xì)講解
一、提要
什么是Boost.Pool?
Boost Pool 是一個(gè)庫,其中包含一些用于管理內(nèi)存的類。雖然 C++ 程序通常使用 new 來動(dòng)態(tài)分配內(nèi)存,但如何提供內(nèi)存的細(xì)節(jié)取決于標(biāo)準(zhǔn)庫和操作系統(tǒng)的實(shí)現(xiàn)。例如,使用 Boost.Pool,您可以加速內(nèi)存管理以更快地為您的程序提供內(nèi)存。
Boost.Pool 不會(huì)改變新系統(tǒng)或操作系統(tǒng)的行為。 Boost.Pool 之所以有效,是因?yàn)槭紫葟牟僮飨到y(tǒng)請(qǐng)求托管內(nèi)存——例如使用 new。從外面看,你的程序已經(jīng)分配了內(nèi)存,但在內(nèi)部,內(nèi)存還不是必需的,交給 Boost.Pool 來管理。
二、關(guān)于Boost.Pool應(yīng)用
Boost.Pool 以相同大小對(duì)內(nèi)存段進(jìn)行分區(qū)。每次您從 Boost.Pool 請(qǐng)求內(nèi)存時(shí),庫都會(huì)訪問下一個(gè)空閑段并將該段中的內(nèi)存分配給您。然后將整個(gè)段標(biāo)記為已使用,無論您實(shí)際需要該段的多少字節(jié)。
這種內(nèi)存管理概念稱為簡單隔離存儲(chǔ)。這是 Boost.Pool 唯一支持的概念。如果必須經(jīng)常創(chuàng)建和銷毀許多相同大小的對(duì)象,則它特別有用。在這種情況下,可以快速提供和釋放所需的內(nèi)存。
?? Boost.Pool 提供類 boost::simple_segregated_storage 來創(chuàng)建和管理隔離內(nèi)存。 boost::simple_segregated_storage 是一個(gè)低級(jí)類,您通常不會(huì)在程序中直接使用它。它僅在示例1中用于說明簡單的隔離存儲(chǔ)。 Boost.Pool 中的所有其他類都在內(nèi)部基于 boost::simple_segregated_storage。
案例1. 使用 boost::simple_segregated_storage
#include <boost/pool/simple_segregated_storage.hpp> #include <vector> #include <cstddef> int main() { boost::simple_segregated_storage<std::size_t> storage; std::vector<char> v(1024); storage.add_block(&v.front(), v.size(), 256); int *i = static_cast<int*>(storage.malloc()); *i = 1; int *j = static_cast<int*>(storage.malloc_n(1, 512)); j[10] = 2; storage.free(i); storage.free_n(j, 1, 512); }
必須包含頭文件 boost/pool/simple_segregated_storage.hpp 才能使用類模板 boost::simple_segregated_storage。示例 4.1 將 std::size_t 作為模板參數(shù)傳遞。此參數(shù)指定傳遞給 boost::simple_segregated_storage 成員函數(shù)的數(shù)字應(yīng)使用哪種類型,以引用例如段的大小。這個(gè)模板參數(shù)的實(shí)際相關(guān)性相當(dāng)?shù)汀?/p>
更有趣的是在 boost::simple_segregated_storage 上調(diào)用的成員函數(shù)。首先,調(diào)用 add_block() 將一個(gè) 1024 字節(jié)的內(nèi)存塊傳遞給存儲(chǔ)。內(nèi)存由向量 v 提供。傳遞給 add_block() 的第三個(gè)參數(shù)指定應(yīng)將內(nèi)存塊劃分為每個(gè) 256 字節(jié)的段。由于內(nèi)存塊的總大小為 1024 字節(jié),因此存儲(chǔ)管理的內(nèi)存由四個(gè)段組成。
對(duì) malloc() 和 malloc_n() 的調(diào)用從存儲(chǔ)中請(qǐng)求內(nèi)存。 malloc() 返回指向空閑段的指針,而 malloc_n() 返回指向一個(gè)或多個(gè)連續(xù)段的指針,這些段在一個(gè)塊中提供所請(qǐng)求的盡可能多的字節(jié)。示例 4.1 使用 malloc_n() 請(qǐng)求一個(gè) 512 字節(jié)的塊。此調(diào)用消耗兩個(gè)段,因?yàn)槊總€(gè)段為 256 字節(jié)。在調(diào)用 malloc() 和 malloc_n() 之后,storage 只剩下一個(gè)未使用的段。
在示例結(jié)束時(shí),所有段都使用 free() 和 free_n() 釋放。在這兩次調(diào)用之后,所有段都可用并且可以使用 malloc() 或 malloc_n() 再次請(qǐng)求。
您通常不直接使用 boost::simple_segregated_storage。 Boost.Pool 提供了其他自動(dòng)分配內(nèi)存的類,無需您自己分配內(nèi)存并將其傳遞給 boost::simple_segregated_storage。
案例2. 使用 boost::object_pool
#include <boost/pool/object_pool.hpp> int main() { boost::object_pool<int> pool; int *i = pool.malloc(); *i = 1; int *j = pool.construct(2); pool.destroy(i); pool.destroy(j); }
案例2 : boost::object_pool
, 的定義地方為 boost/pool/object_pool.hpp
.
與 boost::simple_segregated_storage 不同,boost::object_pool 知道將存儲(chǔ)在內(nèi)存中的對(duì)象的類型。示例 4.2 中的池是用于 int 值的簡單隔離存儲(chǔ)。由池管理的內(nèi)存由段組成,每個(gè)段的大小為 int——例如 4 個(gè)字節(jié)。
一個(gè)區(qū)別是您不需要為 boost::object_pool 提供內(nèi)存。 boost::object_pool 自動(dòng)分配內(nèi)存。在示例 4.2 中,對(duì) malloc() 的調(diào)用使池為 32 個(gè) int 值分配一個(gè)具有空間的內(nèi)存塊。 malloc() 返回一個(gè)指針,指向這 32 個(gè)段中的第一個(gè)段,一個(gè) int 值可以完全適應(yīng)。
請(qǐng)注意 malloc() 返回一個(gè) int* 類型的指針。與示例1 中的 boost::simple_segregated_storage 不同,不需要轉(zhuǎn)換運(yùn)算符。
constructor() 與 malloc() 類似,但通過調(diào)用構(gòu)造函數(shù)來初始化對(duì)象。在示例 4.2 中,j 指的是使用值 2 初始化的 int 對(duì)象。
請(qǐng)注意,調(diào)用 struct() 時(shí),pool 可以從 32 個(gè)段的池中返回一個(gè)空閑段。對(duì) struct() 的調(diào)用不會(huì)使示例 4.2 從操作系統(tǒng)請(qǐng)求內(nèi)存。
在示例 2 中調(diào)用的最后一個(gè)成員函數(shù)是destroy(),它會(huì)釋放一個(gè) int 對(duì)象。
示例3. 使用 boost::object_pool 更改分段大小
#include <boost/pool/object_pool.hpp> #include <iostream> int main() { boost::object_pool<int> pool{32, 0}; pool.construct(); std::cout << pool.get_next_size() << '\n'; pool.set_next_size(8); }
您可以將兩個(gè)參數(shù)傳遞給 boost::object_pool 的構(gòu)造函數(shù)。第一個(gè)參數(shù)設(shè)置當(dāng)調(diào)用 malloc() 或 struct() 請(qǐng)求第一個(gè)段時(shí), boost::object_pool 將分配的內(nèi)存塊的大小。第二個(gè)參數(shù)設(shè)置要分配的內(nèi)存塊的最大大小。
如果 malloc() 或 struct() 被頻繁調(diào)用,以至于內(nèi)存塊中的所有段都被使用,則對(duì)這些成員函數(shù)之一的下一次調(diào)用將導(dǎo)致 boost::object_pool 分配一個(gè)新的內(nèi)存塊,該內(nèi)存塊將是原來的兩倍和上一個(gè)一樣。每次 boost::object_pool 分配一個(gè)新的內(nèi)存塊時(shí),大小都會(huì)加倍。 boost::object_pool 可以管理任意數(shù)量的內(nèi)存塊,但它們的大小會(huì)呈指數(shù)增長。第二個(gè)構(gòu)造函數(shù)參數(shù)允許您限制增長。
boost::object_pool 的默認(rèn)構(gòu)造函數(shù)的作用與示例 4.3 中對(duì)構(gòu)造函數(shù)的調(diào)用作用相同。第一個(gè)參數(shù)將內(nèi)存塊的大小設(shè)置為 32 個(gè) int 值。第二個(gè)參數(shù)指定沒有最大大小。如果傳遞 0,則 boost::object_pool 可以無限期地使內(nèi)存塊的大小翻倍。
示例3 中對(duì) struct() 的調(diào)用使池分配 32 個(gè) int 值的內(nèi)存塊。 pool 最多可以為 malloc() 或 struct() 提供 32 次調(diào)用,而無需向操作系統(tǒng)請(qǐng)求內(nèi)存。如果需要更多內(nèi)存,下一個(gè)要分配的內(nèi)存塊將有 64 個(gè) int 值的空間。
get_next_size() 返回下一個(gè)要分配的內(nèi)存塊的大小。 set_next_size() 讓您設(shè)置下一個(gè)內(nèi)存塊的大小。在示例 4.3 中,get_next_size() 返回 64。對(duì) set_next_size() 的調(diào)用將下一個(gè)要分配的內(nèi)存塊的大小從 64 更改為 8 個(gè) int 值。使用 set_next_size() 可以直接更改下一個(gè)內(nèi)存塊的大小。如果您只想設(shè)置最大大小,請(qǐng)通過第二個(gè)參數(shù)將其傳遞給構(gòu)造函數(shù)。
通過 boost::singleton_pool,Boost.Pool 提供了一個(gè)介于 boost::simple_segregated_storage 和 boost::object_pool 之間的類(參見示例 4)。
案例4. 使用 boost::singleton_pool
#include <boost/pool/singleton_pool.hpp> struct int_pool {}; typedef boost::singleton_pool<int_pool, sizeof(int)> singleton_int_pool; int main() { int *i = static_cast<int*>(singleton_int_pool::malloc()); *i = 1; int *j = static_cast<int*>(singleton_int_pool::ordered_malloc(10)); j[9] = 2; singleton_int_pool::release_memory(); singleton_int_pool::purge_memory(); }
boost::singleton_pool 在 boost/pool/singleton_pool.hpp 中定義。此類與 boost::simple_segregated_storage 類似,因?yàn)樗€期望段大小作為模板參數(shù),而不是要存儲(chǔ)的對(duì)象的類型。這就是為什么諸如 ordered_malloc() 和 malloc() 之類的成員函數(shù)返回一個(gè) void* 類型的指針,它必須顯式地強(qiáng)制轉(zhuǎn)換。
這個(gè)類也類似于 boost::object_pool,因?yàn)樗鼤?huì)自動(dòng)分配內(nèi)存。下一個(gè)內(nèi)存塊的大小和可選的最大大小作為模板參數(shù)傳遞。這里的 boost::singleton_pool 與 boost::object_pool 不同:您不能在運(yùn)行時(shí)更改 boost::singleton_pool 中下一個(gè)內(nèi)存塊的大小。
如果您想管理多個(gè)內(nèi)存池,可以使用 boost::singleton_pool 創(chuàng)建多個(gè)對(duì)象。傳遞給 boost::singleton_pool 的第一個(gè)模板參數(shù)是一個(gè)標(biāo)簽。標(biāo)記是用作內(nèi)存池名稱的任意類型。示例 4.4 使用結(jié)構(gòu) int_pool 作為標(biāo)簽來強(qiáng)調(diào) singleton_int_pool 是一個(gè)管理 int 值的池。多虧了標(biāo)簽,多個(gè)單例可以管理不同的內(nèi)存池,即使大小的第二個(gè)模板參數(shù)相同。該標(biāo)簽除了創(chuàng)建單獨(dú)的 boost::singleton_pool 實(shí)例之外沒有其他用途。
boost::singleton_pool 提供了兩個(gè)成員函數(shù)來釋放內(nèi)存:release_memory() 釋放所有當(dāng)前未使用的內(nèi)存塊,purge_memory() 釋放所有內(nèi)存塊——包括當(dāng)前正在使用的內(nèi)存塊。對(duì) purge_memory() 的調(diào)用會(huì)重置 boost::singleton_pool。
release_memory() 和 purge_memory() 將內(nèi)存返回給操作系統(tǒng)。要將內(nèi)存返回到 boost::singleton_pool 而不是操作系統(tǒng),請(qǐng)調(diào)用成員函數(shù),例如 free() 或 ordered_free()。
boost::object_pool 和 boost::singleton_pool 允許你明確地請(qǐng)求內(nèi)存。為此,您可以調(diào)用 malloc() 或 struct() 等成員函數(shù)。 Boost.Pool 還提供了 boost::pool_allocator 類,您可以將其作為分配器傳遞給容器(參見示例 4.5)。
案例5. 使用 boost::pool_allocator
#include <boost/pool/pool_alloc.hpp> #include <vector> int main() { std::vector<int, boost::pool_allocator<int>> v; for (int i = 0; i < 1000; ++i) v.push_back(i); v.clear(); boost::singleton_pool<boost::pool_allocator_tag, sizeof(int)>:: purge_memory(); }
boost::pool_allocator 在 boost/pool/pool_alloc.hpp 中定義。該類是一個(gè)分配器,通常作為第二個(gè)模板參數(shù)從標(biāo)準(zhǔn)庫傳遞給容器。分配器提供容器所需的內(nèi)存。
boost::pool_allocator 基于 boost::singleton_pool。要釋放內(nèi)存,您必須使用標(biāo)簽訪問 boost::singleton_pool 并調(diào)用 purge_memory() 或 release_memory()。示例 4.5 使用標(biāo)簽 boost::pool_allocator_tag。此標(biāo)簽由 Boost.Pool 定義,并由 boost::pool_allocator 用于內(nèi)部 boost::singleton_pool。
當(dāng)示例 4.5 第一次調(diào)用 push_back() 時(shí),v 訪問分配器以獲取請(qǐng)求的內(nèi)存。因?yàn)槭褂昧朔峙淦?boost::pool_allocator,所以分配了一個(gè)具有 32 個(gè) int 值空間的內(nèi)存塊。 v 接收指向該內(nèi)存塊中具有 int 大小的第一個(gè)段的指針。每次后續(xù)調(diào)用 push_back() 時(shí),都會(huì)使用內(nèi)存塊中的另一個(gè)段,直到分配器檢測到需要更大的內(nèi)存塊。
請(qǐng)注意,在使用 purge_memory() 釋放內(nèi)存之前,應(yīng)在容器上調(diào)用 clear()(參見示例 4.5)。調(diào)用 purge_memory() 會(huì)釋放內(nèi)存,但不會(huì)通知容器它不再擁有內(nèi)存。調(diào)用 release_memory() 的危險(xiǎn)性較小,因?yàn)樗会尫盼词褂玫膬?nèi)存塊。
Boost.Pool 還提供了一個(gè)名為 boost::fast_pool_allocator 的分配器(參見示例 4.6)。
示例6. Using boost::fast_pool_allocator
#define BOOST_POOL_NO_MT #include <boost/pool/pool_alloc.hpp> #include <list> int main() { typedef boost::fast_pool_allocator<int, boost::default_user_allocator_new_delete, boost::details::pool::default_mutex, 64, 128> allocator; std::list<int, allocator> l; for (int i = 0; i < 1000; ++i) l.push_back(i); l.clear(); boost::singleton_pool<boost::fast_pool_allocator_tag, sizeof(int)>:: purge_memory(); }
兩種分配器的使用方式相同,但如果您請(qǐng)求連續(xù)的段,則應(yīng)該首選 boost::pool_allocator。 boost::fast_pool_allocator 可以用于分段請(qǐng)求的情況。大體簡化:您將 boost::pool_allocator 用于 std::vector 和 boost::fast_pool_allocator 用于 std::list。
示例 6 說明了哪些模板參數(shù)可以傳遞給 boost::fast_pool_allocator。 boost::pool_allocator 接受相同的參數(shù)。
boost::default_user_allocator_new_delete 是一個(gè)使用 new 分配內(nèi)存塊并使用 delete[] 釋放它們的類。您還可以使用 boost::default_user_allocator_malloc_free,它調(diào)用 malloc() 和 free()。
boost::details::pool::default_mutex 是設(shè)置為 boost::mutex 或 boost::details::pool::null_mutex 的類型定義。 boost::mutex 是支持多個(gè)線程從分配器請(qǐng)求內(nèi)存的默認(rèn)類型。如果宏 BOOST_POOL_NO_MT 的定義如示例 4.6 中所示,則禁用 Boost.Pool 的多線程支持。示例 4.6 中的分配器使用空互斥體。
在示例 6 中傳遞給 boost::fast_pool_allocator 的最后兩個(gè)參數(shù)設(shè)置了第一個(gè)內(nèi)存塊的大小和要分配的內(nèi)存塊的最大大小。
Chapter 1. Boost.SmartPointers (theboostcpplibraries.com)
到此這篇關(guān)于C++ Boost Pool超詳細(xì)講解的文章就介紹到這了,更多相關(guān)C++ Boost Pool內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++運(yùn)行時(shí)獲取類型信息的type_info類與bad_typeid異常
這篇文章主要介紹了C++運(yùn)行時(shí)獲取類型信息的type_info類與bad_typeid異常,是C++入門學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下2016-01-01C++類型轉(zhuǎn)換運(yùn)算符的實(shí)例詳解
這篇文章主要介紹了C++類型轉(zhuǎn)換運(yùn)算符的實(shí)例詳解的相關(guān)資料,希望通過本文大家能夠掌握這部分內(nèi)容,需要的朋友可以參考下2017-09-09C++連接mysql數(shù)據(jù)庫(改進(jìn)版)
C++是大家都非常熟悉的,也是大家平時(shí)辦公中經(jīng)常會(huì)用到的,下面這篇文章主要給大家介紹了關(guān)于C++連接mysql數(shù)據(jù)庫的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-12-12淺談C++/C關(guān)于#define的那些奇奇怪怪的用法
本文主要介紹了C++/C關(guān)于#define的那些奇奇怪怪的用法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-07-07