MAA*_*612 4 c++ stl allocator c++11
我正在尝试实现一个STL样式的容器类,我有一个关于在我的类中使用allocator的问题:
STL中静态成员函数的用途是什么allocator_traits?
到现在为止,我认为我应该实例化allocator_type(可能通过某种空基础优化来改善内存占用).因此,我最终会得到这样的结论:
struct EmptyBaseOpt : allocator_type
{
EmptyBaseOpt(const allocator_type & a, allocator_type::const_pointer p)
: allocator_type(a), prefix_ptr(p) { }
allocator_type::pointer prefix_ptr;
}
EmptyBaseOpt ebo;
Run Code Online (Sandbox Code Playgroud)
然后,我可以通过以下方式使用分配器:
allocator_type & alloc = ebo;
alloc.allocate(100, ebo.prefix_ptr);
Run Code Online (Sandbox Code Playgroud)
另一方面,allocator_traits在C++ 11中似乎意味着以下用法:
std::allocator_traits<allocator_type>::allocate(100, ebo.prefix_ptr);
Run Code Online (Sandbox Code Playgroud)
我想这个静态allocate成员函数可能会allocator_type通过其默认构造函数创建一个临时的临时实例.但这导致了以下问题:
如果allocator_type是有状态分配器会发生什么?如果我使用静态成员函数allocator_traits而不是从一个实例中调用非静态方法,这样的分配器是否能够保持其状态allocator_type?
allocator_type如果我可以直接使用静态成员函数,为什么我要实例化并烦恼像EBO这样的东西allocator_traits呢?
如前所述,我的理解是,任何类类模板参数都应该在我的容器类中实例化,以便允许这些参数的有状态版本.这种理解是否正确,它如何适应静态成员函数allocator_traits?
另一方面,C++ 11中的allocator_traits似乎意味着以下用法:
Run Code Online (Sandbox Code Playgroud)std::allocator_traits<allocator_type>::allocate(100, ebo.prefix_ptr);
不,你错过了该函数调用最重要的参数:分配器.
我想这个静态分配成员函数可能会通过其默认构造函数创建一个临时的临时实例allocator_type.
不,因为您将allocator参数传递给函数.
如果allocator_type是有状态分配器会发生什么?
它工作正常,因为您将有状态分配器作为参数传递给使用它的函数.
如果我可以直接使用allocator_traits中的静态成员函数,为什么我要实例化allocator_type而烦恼像EBO这样的东西呢?
因为你不能使用它们.
如前所述,我的理解是,任何类类模板参数都应该在我的容器类中实例化,以便允许这些参数的有状态版本.这种理解是否正确,它如何适应allocator_traits中的静态成员函数?
是的,您的理解是正确的,allocator_traits如果您正确使用它,它就适合.
重点allocator_traits是为大多数Allocator接口提供合理的默认值.这有两个目的:
首先,它是简单的定义在C++ 11的分配(你只需要提供value_type,allocate,deallocate,再结合分配器和模板的构造operator==和operator!=),所以编写简单的自定义分配器现在要简单得多.
其次,它允许C++ 11容器使用仅满足C++ 03分配器要求的现有分配器.C++ 03分配器没有定义嵌套成员,例如propagate_on_container_swapC++ 11容器所寻找的,或者新的可变参数construct(pointer, Args&&...)成员,它允许使用任何参数构造对象,而不仅仅是复制构造(允许emplace工作).因此,通过在allocator_traits大多数Allocator接口中包含分配器的使用给出合理的默认值,因此使用带有容器的自定义分配器的现有C++ 03代码std::vector如果使用C++ 11重新编译将不会突然失败.在std::vector执行只有通过使用新成员allocator_traits 类型,因此自定义分配器未更新以提供属于C++ 11分配器要求的所有新成员并不重要.
你似乎已经错过了一个事实,即所有的静态成员函数allocator_traits取Alloc &作为第一个参数.也就是说,他们使用分配器类型的对象来完成他们的工作.
这种" allocator_traits仅通过分配器访问"策略的原因是,allocator_traits如果分配器类型本身不提供分配器操作,则某些成员提供分配器操作的默认实现.这适用于在C++ 11中添加到分配器要求但在C++ 03中不存在的所有成员.例如construct,如果分配器类型不提供合适的,则将调用放置new运算符::newconstruct功能.因此,这些默认值允许为C++ 03编写的分配器在C++ 11容器中保持不变.
此外,使用allocator_traits允许更多的可定制性.allocator_traits可以为特定的allocator类指定,并且可以通过对Alloc &参数的不同调用来实现trait函数.
所以你实例化的假设allocator_type是正确的.不同之处在于您不应该直接调用其成员函数(因为它们可能不存在),而是通过静态访问器调用allocator_traits.