STL Container:构造函数的Allocator参数和作用域分配器 [英] STL Container: Constructor's Allocator parameter and scoped allocators

查看:326
本文介绍了STL Container:构造函数的Allocator参数和作用域分配器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有一个模板参数为STL容器选择自定义分配器。花了一段时间,但我想我明白它是如何工作的。不知怎的,它不是真的很好,因为给定的分配器类型不是直接使用,而是反弹到另一种类型的分配器。最后我可以使用它。



阅读 API 我认识到,还有可能给分配器作为构造函数参数。但是如何知道容器使用哪种分配器,如果它从模板参数里面重新绑定给定的分配器?



此外,我读到C ++ 11现在使用作用域分配器允许重用容器的分配器用于其包含容器。



不幸的是,我没能找到任何可以解释这个问题的东西。 。感谢您的答案!

解决方案


但是如何知道容器使用哪种分配器,if it
从模板参数内部重新绑定给定的分配器


始终提供分配器< T& ; c>到构造函数(其中 T 是容器的 value_type )。容器将其转换为 Allocator< U> 是必要的,其中 U 是容器的一些内部数据结构。需要 Allocator 来提供此类转换构造函数,例如:

 模板< class T> class allocator {
...
template< class U> allocator(const allocator< U>&);




此外,我读到C ++ 11现在使用范围分配器
为其包含容器重用一个容器的分配器。


有一个名为 scoped_allocator_adaptor 分配器适配器

  template< class OuterAlloc,class ... InnerAllocs> 
class scoped_allocator_adaptor:public OuterAlloc
{
...
};

从C ++ 11:


类模板 scoped_allocator_adaptor 是一个分配器模板
,它指定要由
a使用的内存资源(外部分配器)容器(像任何其他分配器一样),并且还指定要传递给容器内每个元素
的构造函数的内部
分配器资源。这个适配器被实例化一个外部和
零或多个内部分配器类型。如果实例化只有一个
分配器类型,内部分配器变成
scoped_allocator_adaptor 本身,因此使用相同的分配器
资源容器和容器中的每个元素,
如果元素本身是容器,则它们的每个元素
递归。如果使用多个分配器实例化,第一个
分配器是容器使用的外部分配器,第二个
分配器传递给容器的元素的构造函数
,如果元素本身是容器,第三个分配器是
传递给元素的元素,等等。如果容器嵌套
到大于分配器数量的深度,则对于任何剩余的
递归,最后的分配器
被重复使用,如在单分配器的情况下。 [注意 scoped_allocator_adaptor 派生自
外部分配器类型,因此它可以替代外部分配器
类型在大多数表达式。 - end note ]


因此,只有指定 scoped_allocator_adaptor 作为您容器的分配器。


如何实现范围分配器启用容器
与不知道有范围的容器大致不同?


关键是容器现在处理其分配器一个新的类 allocator_traits ,而不是直接处理分配器。而且容器必须 使用 allocator_traits 来执行某些操作,例如构建和销毁 value_type 容器。

可以提供一个名为<$>的成员 c $ c>构造,它将使用给定的参数在某个地址构造一个类型:

  template< class T> class Allocator {
...
template< class U,class ... Args>
void construct(U * p,Args& ... args);
};

如果分配器不提供此成员, allocator_traits 将提供一个默认实现。无论如何,容器必须使用此构造函数构造所有 value_type 通过 allocator_traits 使用它,并且不直接使用 allocator

  allocator_traits< allocator_type> :: construct(the_allocator,* ugly details *); 

scoped_allocator_adaptor 提供自定义构造函数 allocator_traits 将转发到利用 uses_allocator traits将正确的分配器传递给 value_type 构造函数。容器保持着对这些细节的无知。容器只需要知道它必须使用 allocator_traits构造函数构造 value_type



有更多的细节,容器必须处理以正确处理状态分配器。虽然这些细节也通过容器没有做任何假设,但通过 allocator_traits 获得所有属性和行为来处理。容器甚至不能假定指针 T * 。相反,这种类型是通过请求 allocator_traits 找到的。



简而言之,构建一个C ++ 11容器,学习 allocator_traits 。然后,当您的客户使用 scoped_allocator_adaptor 时,您可以免费获得作用域分配器行为。


There is a template parameter for STL containers to chose a custom allocator. It took a while, but I think I understand how it works. Somehow it isn't really nice because the given allocator type isn't used directly but it is rebound to the allocator of another type. Finally I can work with it.

After reading the API I recognized that there is also the possibility to give allocators as constructor parameter. But how do I know which kind of allocator the container uses, if it internally rebinds the given allocator from the template parameter?

Additionally I read that C++11 now uses scoped allocators which allow to reuse the allocator of a container for its containing containers. How does the implementation of a scoped allocator enabled container roughly differs from one that is not aware of scoped containers?

Unfortunately I wasn't able to find anything that could explain this. Thanks for answers!

解决方案

But how do I know which kind of allocator the container uses, if it internally rebinds the given allocator from the template parameter?

Always supply an Allocator<T> to the constructor (where T is the value_type of the container). The container will convert it to an Allocator<U> is necessary where U is some internal data structure of the container. The Allocator is required to supply such converting constructors, e.g.:

template <class T> class allocator {
    ...
    template <class U> allocator(const allocator<U>&);

Additionally I read that C++11 now uses scoped allocators which allow to reuse the allocator of a container for its containing containers.

Well, to be more precise, C++11 has an allocator adaptor called scoped_allocator_adaptor:

template <class OuterAlloc, class... InnerAllocs>
class scoped_allocator_adaptor : public OuterAlloc
{
    ...
};

From C++11:

The class template scoped_allocator_adaptor is an allocator template that specifies the memory resource (the outer allocator) to be used by a container (as any other allocator does) and also specifies an inner allocator resource to be passed to the constructor of every element within the container. This adaptor is instantiated with one outer and zero or more inner allocator types. If instantiated with only one alloca- tor type, the inner allocator becomes the scoped_allocator_adaptor itself, thus using the same allocator resource for the container and every element within the container and, if the elements themselves are con- tainers, each of their elements recursively. If instantiated with more than one allocator, the first allocator is the outer allocator for use by the container, the second allocator is passed to the constructors of the container’s elements, and, if the elements themselves are containers, the third allocator is passed to the elements’ elements, and so on. If containers are nested to a depth greater than the number of allocators, the last allocator is used repeatedly, as in the single-allocator case, for any remaining recursions. [Note: The scoped_allocator_adaptor is derived from the outer allocator type so it can be substituted for the outer allocator type in most expressions. — end note ]

So you only get the scoped allocators behavior if you specify a scoped_allocator_adaptor as the allocator for your container.

How does the implementation of a scoped allocator enabled container roughly differs from one that is not aware of scoped containers?

The key is that the container now deals with its allocator via a new class called allocator_traits instead of dealing with the allocator directly. And the container must use allocator_traits for certain operations such as constructing and destructing value_types in the container. The container must not talk to the allocator directly.

For example, allocators may provide a member called construct that will construct a type at a certain address using the given arguments:

template <class T> class Allocator {
     ...
    template<class U, class... Args>
        void construct(U* p, Args&&... args);
};

If an allocator does not provide this member, allocator_traits will provide a default implementation. In any event, the container must construct all value_types using this construct function, but using it through allocator_traits, and not using the allocator directly:

allocator_traits<allocator_type>::construct(the_allocator, *ugly details*);

The scoped_allocator_adaptor provides custom construct functions which allocator_traits will forward to which take advantage of the uses_allocator traits and passes the correct allocator along to the value_type constructor. The container remains blissfully ignorant of these details. The container only has to know that it must construct the value_type using the allocator_traits construct function.

There are more details the container must have to deal with to correctly handle stateful allocators. Though these details too are dealt with by having the container not make any assumptions but get all properties and behaviors via allocator_traits. The container can not even assume that pointer is T*. Rather this type is found by asking allocator_traits what it is.

In short, to build a C++11 container, study up on allocator_traits. And then you get scoped allocator behavior for free when your clients use the scoped_allocator_adaptor.

这篇关于STL Container:构造函数的Allocator参数和作用域分配器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆