Mr.*_*C64 16 c++ memory-management stl allocator c++11
我将构建一个自定义分配器,预分配一个大块(数组)来存储N
某些类的元素T
,然后只需增加数组内的索引来为服务分配请求.
因为我不希望对预分配块中的元素进行任何初始化,所以这样的东西不起作用:
T buffer[N];
Run Code Online (Sandbox Code Playgroud)
因为在这种情况下,T
将为N
块的元素调用构造函数.
既然我的理解是std::aligned_storage
不调用T
构造函数,我想使用std::aligned_storage
,像这样:
std::aligned_storage<
N * sizeof(T),
std::alignment_of<T>::value
>::type buffer;
T* base = static_cast<T*>( static_cast<void*>(&buffer) );
Run Code Online (Sandbox Code Playgroud)
然后,当请求T的分配(直到(base+N)
)时,分配器可以仅增加基指针,并且在需要时可以在适当的位置构建T (具有放置new
).
我想使用此方案为STL容器定义自定义分配器.但是,在我看来,重新绑定可能存在问题.事实上,如果我的理解是正确的,一个STL分配器应支持从类型重新绑定T
到一个类型U
,例如,因为喜欢的容器std::list<T>
(或其它基于节点的容器一样std::map
)使用allocator分配的节点上,但不是类型T
,但不同type U
(包含T
节点的"header"开头信息).那么,上述std::aligned_storage
方法是否适用于重新绑定?或者(我认为)T
s 的正确对齐并不意味着另一种不同类型的正确对齐U
?
怎么可以解决这个问题?
我怎样才能定义上述内容buffer
以使其适用于重新绑定到某种不同类型U
?
这个问题应该从不同的角度受到攻击吗?如果是这样,什么?
How*_*ant 11
你走在正确的轨道上.
一个令人恼火的细节是,分配器的副本必须比较相等,甚至转换(反弹)副本.比较相等意味着他们可以释放彼此的指针.所以容器中,如std::list<int>
将重新绑定your_alloc<int>
到your_alloc<node<int>>
,然后构建一个your_alloc<node<int>>
使用your_alloc<int>
.从技术上讲,你your_alloc<node<int>>
必须解除分配的指针your_alloc<int>
.
这是我尝试满足这一要求.随意复制/修改/滥用此代码.我的目的是教育,而不是成为世界的分配器供应商(无论如何都不会有利可图:-)).
这个例子采用了略微不同的对齐方法:我碰巧知道在我感兴趣的平台(OS X,iOS)上malloc
返回16字节对齐的内存,所以我的所有自定义分配器都需要返回.您可以将该数字更改为适合您系统的数字.
对准这硬连线意味着单个池可以安全地提供一些allocator<int>
和allocator<node<int>>
,因为他们是排列所有的16个字节(这就是足够了).并且它还意味着副本,甚至是转换后的副本,可以检测指针何时指向缓冲区,因为副本都共享相同的缓冲区.
换句话说,C++委员会已经有效地指定了分配器是引用类型:副本是等效的并且指向相同的内存池.
您可以使用实际嵌入到分配器中的内存池来避免作弊,但在某些实现中只能使用某些容器,并且您无法使用标准中的引用来备份.
归档时间: |
|
查看次数: |
1647 次 |
最近记录: |