我想设计一个类模板,它使用一个分配器类型(如标准17.6.3.5节中定义的那样)作为模板参数。我看到了std::allocator_traits<A>如何用默认设置来帮助填充缺少的A成员。除此之外,标准库或boost中是否有有助于正确使用分配程序的内容?
特别是:
std::allocator_traits<A>::propagate_on_container_copy_assignment这样的类型,我必须在每个类的特殊成员函数中检查这些东西吗?每个类都有一个A类型的成员?或者我是否可以使用一些包装器类型作为成员来处理这些问题?如果我想通过在用户可见对象旁边存储额外的数据来减少分配的数量,。
template<typename T, typename A>
class MyClass
{
private:
//...
struct storage {
int m_special_data;
T m_obj;
};
typedef typename std::allocator_traits<A>::template rebind_alloc<storage>
storage_alloc;
typedef typename std::allocator_traits<A>::template rebind_traits<storage>
storage_traits;
storage_alloc m_alloc;
static T* alloc(T&& obj)
{
storage_traits::pointer sp = storage_traits::allocate(m_alloc, 1);
sp->m_special_data = 69105;
return ::new(&sp->m_obj) T(std::move(obj));
}
//...
};发布于 2012-06-16 00:35:46
我不知道有什么可以让生活变得更简单,allocator_traits确实通过提供所有的样板代码来简化分配器的编写,但它无助于使用分配器。
为了在C++03和C++11代码中使用单个分配程序API (我在GCC 4.7中添加了<ext/alloc_traits.h> ),类模板__gnu_cxx::__alloc_traits提供了一个一致的API,它在C++11模式中使用allocator_traits,并在C++03模式下直接调用分配程序上的相关成员函数。
propagate_on_container_copy_assignment为false,且现有容量大于源对象的大小,则可以重用现有内存(如果为true,且新的分配器不相等,则不能重用旧内存,因为在替换分配程序之后不可能对其进行重新分配),但这种优化对于基于节点的容器(如列表或映射)没有多大帮助。
返回::new(&sp->m_obj) T(std::move(obj));
使用
a(m_alloc);std::allocator_traits::construct(a,&sp->m_obj,std::move(obj));返回&sp->m_obj;
如前所述,使用分配程序的容器使用allocator_traits<A>::construct创建元素类型T本身,但是分配的任何其他类型(例如storage)都不能使用construct。
如果storage本身是构造的,那么它将构造storage::m_obj,除非该成员是一个可以保留未初始化的类型,如std::aligned_storage<sizeof(T)>,该类型可以在以后由allocator_traits<A>::construct显式初始化。或者,单独构造需要非平凡结构的每个成员,例如,如果storage也有一个string成员:
storage_traits::pointer sp = storage_traits::allocate(m_alloc, 1);
sp->m_special_data = 69105;
::new (&sp->m_str) std::string("foobar");
A a(m_alloc);
std::allocator_traits<A>::construct(a, &sp->m_obj, std::move(obj));
return &sp->m_obj;m_special_data成员是一个微不足道的类型,因此它的生存期在为其分配存储时就开始了。m_str和m_obj成员需要非平凡的初始化,因此它们的生存期是在构造函数完成时开始的,这分别是通过placement和construct调用完成的。
编辑:我最近了解到该标准有一个缺陷(我已经报告过),对construct的调用不需要使用回弹分配器,所以这些行:
A a(m_alloc);
std::allocator_traits<A>::construct(a, &sp->m_obj, std::move(obj));可替换为:
std::allocator_traits<storage_alloc>::construct(m_alloc, &sp->m_obj, std::move(obj));这会让生活稍微轻松一些。
https://stackoverflow.com/questions/9689328
复制相似问题