我最近一直在开发基于内存池的自定义分配器,该内存池在分配器的多个实例之间共享。
目的是分配器与 STL 和基于标准 C++ 的容器兼容,例如向量、双端队列、映射、字符串等
然而,特别是一些事情让我有些困惑。容器的各种实现,例如std::vector,std::string使用小缓冲区优化 - 基于堆栈的分配来满足小的初始内存需求。
例如 MSVC9.1 在 basic_string 类中有以下成员:
union _Bxty
{ // storage for small buffer or pointer to larger one
_Elem _Buf[_BUF_SIZE];
_Elem *_Ptr;
char _Alias[_BUF_SIZE]; // to permit aliasing
} _Bx;
我看不出在实例化此类容器时如何哄骗实现只使用提供的分配器而不使用 SBO。我问是因为实现自定义分配器的目的之一是能够在共享内存上下文中使用它们,其中共享内存的数量可能小于 SBO 限制,一些不同的实现可能会使用。
例如,我希望有两个 std::string 实例,每个进程共享一个可能小于或等于 SBO 上限的公共内存块。
typedef std::vector<int,mysharedmemallocator> shmvtype;
shmvtype v(2,0); //<-- if SBO then error as memory is allocated on
//stack not via the allocator
v[1] = 1234; //<-- if SBO then error as wrong piece of memory
// is being modified.
让我们看另一个不基于共享内存的示例,因为它似乎对某些人来说过于复杂。假设我想用一个分配器专门化我的 std::basic_string 或 std::vector 等,该分配器在将指针返回给调用实体之前用值 0xAB 填充它分配的内存,除了奇思妙想之外没有其他原因。
专用于此新分配器但也使用 SBO 的容器将不会将其基于 SBO 的内存填充为 0xAB 模式。例如:
typedef std::basic_string<char,myfillmemallocator> stype
stype s;
s.resize(2);
assert(s[0] == 0xAB); // if SBO this will fail.