日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

C++?Boost?Pool超詳細講解_C 語言

作者:無水先生 ? 更新時間: 2022-12-13 編程語言

一、提要

????????什么是Boost.Pool?

????????Boost Pool 是一個庫,其中包含一些用于管理內存的類。雖然 C++ 程序通常使用 new 來動態分配內存,但如何提供內存的細節取決于標準庫和操作系統的實現。例如,使用 Boost.Pool,您可以加速內存管理以更快地為您的程序提供內存。

????????Boost.Pool 不會改變新系統或操作系統的行為。 Boost.Pool 之所以有效,是因為首先從操作系統請求托管內存——例如使用 new。從外面看,你的程序已經分配了內存,但在內部,內存還不是必需的,交給 Boost.Pool 來管理。

二、關于Boost.Pool應用

????????Boost.Pool 以相同大小對內存段進行分區。每次您從 Boost.Pool 請求內存時,庫都會訪問下一個空閑段并將該段中的內存分配給您。然后將整個段標記為已使用,無論您實際需要該段的多少字節。

????????這種內存管理概念稱為簡單隔離存儲。這是 Boost.Pool 唯一支持的概念。如果必須經常創建和銷毀許多相同大小的對象,則它特別有用。在這種情況下,可以快速提供和釋放所需的內存。

?????????? Boost.Pool 提供類 boost::simple_segregated_storage 來創建和管理隔離內存。 boost::simple_segregated_storage 是一個低級類,您通常不會在程序中直接使用它。它僅在示例1中用于說明簡單的隔離存儲。 Boost.Pool 中的所有其他類都在內部基于 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 作為模板參數傳遞。此參數指定傳遞給 boost::simple_segregated_storage 成員函數的數字應使用哪種類型,以引用例如段的大小。這個模板參數的實際相關性相當低。

????????更有趣的是在 boost::simple_segregated_storage 上調用的成員函數。首先,調用 add_block() 將一個 1024 字節的內存塊傳遞給存儲。內存由向量 v 提供。傳遞給 add_block() 的第三個參數指定應將內存塊劃分為每個 256 字節的段。由于內存塊的總大小為 1024 字節,因此存儲管理的內存由四個段組成。

????????對 malloc() 和 malloc_n() 的調用從存儲中請求內存。 malloc() 返回指向空閑段的指針,而 malloc_n() 返回指向一個或多個連續段的指針,這些段在一個塊中提供所請求的盡可能多的字節。示例 4.1 使用 malloc_n() 請求一個 512 字節的塊。此調用消耗兩個段,因為每個段為 256 字節。在調用 malloc() 和 malloc_n() 之后,storage 只剩下一個未使用的段。

????????在示例結束時,所有段都使用 free() 和 free_n() 釋放。在這兩次調用之后,所有段都可用并且可以使用 malloc() 或 malloc_n() 再次請求。

????????您通常不直接使用 boost::simple_segregated_storage。 Boost.Pool 提供了其他自動分配內存的類,無需您自己分配內存并將其傳遞給 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 知道將存儲在內存中的對象的類型。示例 4.2 中的池是用于 int 值的簡單隔離存儲。由池管理的內存由段組成,每個段的大小為 int——例如 4 個字節。

????????一個區別是您不需要為 boost::object_pool 提供內存。 boost::object_pool 自動分配內存。在示例 4.2 中,對 malloc() 的調用使池為 32 個 int 值分配一個具有空間的內存塊。 malloc() 返回一個指針,指向這 32 個段中的第一個段,一個 int 值可以完全適應。

????????請注意 malloc() 返回一個 int* 類型的指針。與示例1?中的 boost::simple_segregated_storage 不同,不需要轉換運算符。

????????constructor() 與 malloc() 類似,但通過調用構造函數來初始化對象。在示例 4.2 中,j 指的是使用值 2 初始化的 int 對象。

????????請注意,調用 struct() 時,pool 可以從 32 個段的池中返回一個空閑段。對 struct() 的調用不會使示例 4.2 從操作系統請求內存。

在示例 2 中調用的最后一個成員函數是destroy(),它會釋放一個 int 對象。

示例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);
}

????????您可以將兩個參數傳遞給 boost::object_pool 的構造函數。第一個參數設置當調用 malloc() 或 struct() 請求第一個段時, boost::object_pool 將分配的內存塊的大小。第二個參數設置要分配的內存塊的最大大小。

????????如果 malloc() 或 struct() 被頻繁調用,以至于內存塊中的所有段都被使用,則對這些成員函數之一的下一次調用將導致 boost::object_pool 分配一個新的內存塊,該內存塊將是原來的兩倍和上一個一樣。每次 boost::object_pool 分配一個新的內存塊時,大小都會加倍。 boost::object_pool 可以管理任意數量的內存塊,但它們的大小會呈指數增長。第二個構造函數參數允許您限制增長。

????????boost::object_pool 的默認構造函數的作用與示例 4.3 中對構造函數的調用作用相同。第一個參數將內存塊的大小設置為 32 個 int 值。第二個參數指定沒有最大大小。如果傳遞 0,則 boost::object_pool 可以無限期地使內存塊的大小翻倍。

????????示例3 中對 struct() 的調用使池分配 32 個 int 值的內存塊。 pool 最多可以為 malloc() 或 struct() 提供 32 次調用,而無需向操作系統請求內存。如果需要更多內存,下一個要分配的內存塊將有 64 個 int 值的空間。

????????get_next_size() 返回下一個要分配的內存塊的大小。 set_next_size() 讓您設置下一個內存塊的大小。在示例 4.3 中,get_next_size() 返回 64。對 set_next_size() 的調用將下一個要分配的內存塊的大小從 64 更改為 8 個 int 值。使用 set_next_size() 可以直接更改下一個內存塊的大小。如果您只想設置最大大小,請通過第二個參數將其傳遞給構造函數。

????????通過 boost::singleton_pool,Boost.Pool 提供了一個介于 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 類似,因為它還期望段大小作為模板參數,而不是要存儲的對象的類型。這就是為什么諸如 ordered_malloc() 和 malloc() 之類的成員函數返回一個 void* 類型的指針,它必須顯式地強制轉換。

????????這個類也類似于 boost::object_pool,因為它會自動分配內存。下一個內存塊的大小和可選的最大大小作為模板參數傳遞。這里的 boost::singleton_pool 與 boost::object_pool 不同:您不能在運行時更改 boost::singleton_pool 中下一個內存塊的大小。

????????如果您想管理多個內存池,可以使用 boost::singleton_pool 創建多個對象。傳遞給 boost::singleton_pool 的第一個模板參數是一個標簽。標記是用作內存池名稱的任意類型。示例 4.4 使用結構 int_pool 作為標簽來強調 singleton_int_pool 是一個管理 int 值的池。多虧了標簽,多個單例可以管理不同的內存池,即使大小的第二個模板參數相同。該標簽除了創建單獨的 boost::singleton_pool 實例之外沒有其他用途。

????????boost::singleton_pool 提供了兩個成員函數來釋放內存:release_memory() 釋放所有當前未使用的內存塊,purge_memory() 釋放所有內存塊——包括當前正在使用的內存塊。對 purge_memory() 的調用會重置 boost::singleton_pool。

????????release_memory() 和 purge_memory() 將內存返回給操作系統。要將內存返回到 boost::singleton_pool 而不是操作系統,請調用成員函數,例如 free() 或 ordered_free()。

????????boost::object_pool 和 boost::singleton_pool 允許你明確地請求內存。為此,您可以調用 malloc() 或 struct() 等成員函數。 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 中定義。該類是一個分配器,通常作為第二個模板參數從標準庫傳遞給容器。分配器提供容器所需的內存。

????????boost::pool_allocator 基于 boost::singleton_pool。要釋放內存,您必須使用標簽訪問 boost::singleton_pool 并調用 purge_memory() 或 release_memory()。示例 4.5 使用標簽 boost::pool_allocator_tag。此標簽由 Boost.Pool 定義,并由 boost::pool_allocator 用于內部 boost::singleton_pool。

????????當示例 4.5 第一次調用 push_back() 時,v 訪問分配器以獲取請求的內存。因為使用了分配器 boost::pool_allocator,所以分配了一個具有 32 個 int 值空間的內存塊。 v 接收指向該內存塊中具有 int 大小的第一個段的指針。每次后續調用 push_back() 時,都會使用內存塊中的另一個段,直到分配器檢測到需要更大的內存塊。

????????請注意,在使用 purge_memory() 釋放內存之前,應在容器上調用 clear()(參見示例 4.5)。調用 purge_memory() 會釋放內存,但不會通知容器它不再擁有內存。調用 release_memory() 的危險性較小,因為它只釋放未使用的內存塊。

????????Boost.Pool 還提供了一個名為 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();
}

????????兩種分配器的使用方式相同,但如果您請求連續的段,則應該首選 boost::pool_allocator。 boost::fast_pool_allocator 可以用于分段請求的情況。大體簡化:您將 boost::pool_allocator 用于 std::vector 和 boost::fast_pool_allocator 用于 std::list。

????????示例? 6 說明了哪些模板參數可以傳遞給 boost::fast_pool_allocator。 boost::pool_allocator 接受相同的參數。

????????boost::default_user_allocator_new_delete 是一個使用 new 分配內存塊并使用 delete[] 釋放它們的類。您還可以使用 boost::default_user_allocator_malloc_free,它調用 malloc() 和 free()。

????????boost::details::pool::default_mutex 是設置為 boost::mutex 或 boost::details::pool::null_mutex 的類型定義。 boost::mutex 是支持多個線程從分配器請求內存的默認類型。如果宏 BOOST_POOL_NO_MT 的定義如示例 4.6 中所示,則禁用 Boost.Pool 的多線程支持。示例 4.6 中的分配器使用空互斥體。

????????在示例? 6 中傳遞給 boost::fast_pool_allocator 的最后兩個參數設置了第一個內存塊的大小和要分配的內存塊的最大大小。

Chapter?1.?Boost.SmartPointers (theboostcpplibraries.com)

原文鏈接:https://yamagota.blog.csdn.net/article/details/127045999

欄目分類
最近更新