7

我最近一直在开发基于内存池的自定义分配器,该内存池在分配器的多个实例之间共享。

目的是分配器与 STL 和基于标准 C++ 的容器兼容,例如向量、双端队列、映射、字符串等

然而,特别是一些事情让我有些困惑。容器的各种实现,例如std::vectorstd::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 上限的公共内存块。

可能相关:std::vector 可以利用小缓冲区优化吗?

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.
4

1 回答 1

5

实现自定义分配器的目的之一是能够在共享内存上下文中使用它们

这可能是你打算用它做的,但这不是它们存在的原因。事实上,除了在 C++98/03 中,在对象之间共享分配的内存basic_string是不合法的。它们可以共享分配器对象,因此它们可以从同一个地方获取它们的内存。但是修改一个对象影响另一个不相关的对象是违法的;每个实例必须是分开的。

写入时复制字符串仅起作用,因为系统假定对字符的任何非常量访问都将写入该字符,从而执行复制。而在 C++11 中,甚至basic_string禁止做这样的写时复制风格的东西。

例如,我希望有两个 std::string 实例,每个进程共享一个可能小于或等于 SBO 上限的公共内存块。

如果不编写自己的课程,这是不可能的。分配器只控制内存的来源。您想要的是有保证的写时复制字符串或某种共享字符串类。

你想要的需要一个专门为此目的设计的容器类。

于 2012-12-03T05:42:56.717 回答