我最近一直在努力开发基于内存池的自定义分配器,它在分配器的多个实例之间共享。
意图是分配器与基于STL和标准C ++的容器兼容,例如vector,deque,map,string等
然而,特别是某些事情让我有些困惑。容器的各种实现,例如 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上限的存储器 限制。
可能相关:May std::vector make use of small buffer optimization?
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.
答案 0 :(得分:5)
实现自定义分配器的意图之一是能够在共享内存上下文中使用它们
这可能是你打算用它做的,但这并不是它们存在的原因。实际上,除了C ++ 98/03中的basic_string
之外,共享在对象之间分配内存是不合法的。他们可以共享分配器对象,因此他们可以从同一个地方获取内存。但修改一个对象以影响另一个不相关的对象是违法的;每个实例必须是分开的。
写入时复制字符串仅起作用,因为系统假定对字符的任何非常量访问都会写入,从而执行复制。而在C ++ 11中,即使basic_string
也禁止进行像这样的copy-on-write风格的东西。
例如,我希望有一种情况,我可以在每个进程中有两个std :: string实例共享一个可能小于或等于SBO上限的公共内存块。
如果不写自己的课,那是不可能的。分配器仅控制内存的来源。你想要的是一个有保证的写时复制字符串或某种共享字符串类。
您想要的是需要专门为此目的设计的容器类。