STL容器:构造函数的参数分配器和范围的分配器(STL Container: Constructor

2019-07-31 20:48发布

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

看完之后API我承认,也有给分配器的构造函数的参数的可能性。 但我怎么知道容器使用哪种分配的,如果它在内部重新绑定从模板参数给定的分配?

另外我读C ++ 11现在使用范围的分配器,其允许重复使用的容器的分配器为包含它的容器。 如何做一个范围的分配使容器的实现大致从一个不知道作用域容器的不同?

遗憾的是我没能找到任何可以解释这一点。 感谢您的解答!

Answer 1:

但我怎么知道容器使用哪种分配的,如果它在内部重新绑定从模板参数给定的分配?

总是提供一个Allocator<T>给构造(其中Tvalue_type容器)。 容器将其转换为一个Allocator<U>是必要的,其中U是容器的一些内部数据结构。 该Allocator是提供这种转换的构造,例如,需要:

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

另外我读C ++ 11现在使用范围的分配器,其允许重复使用的容器的分配器为包含它的容器。

好了,更准确地说,C ++ 11有一个名为分配器适配器 scoped_allocator_adaptor

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

从C ++ 11:

类模板scoped_allocator_adaptor是一个分配器模板指定存储器资源(外侧分配器),以由一个容器中(作为任何其他分配器那样),还指定一个内分配器资源将被传递到每个元素的构造方法的容器内。 该适配器被实例化与一个外部和零种或多个内分配器类型。 如果只用一个分配器类型实例化,所述内分配器成为scoped_allocator_adaptor本身,从而使用用于容器相同的分配器资源和所述容器内的每个元素,并且如果元素本身是CON组tainers,其每个元素的递归。 如果具有多于一个分配器实例中,第一分配器是用于利用外分配器由容器中,第二分配器被传递到容器的元件的构造,并且,如果所述元件本身是容器,所述第三分配器被传递到元素的元素,依此类推。 如果容器被嵌套的深度大于分配器的数量越多,最后分配器被重复使用,如在单个分配器的情况下,对任何剩余的递归。 [ scoped_allocator_adaptor从外分配器类型衍生的,因此它可以被替换为在大多数表达式外分配器类型。 - 注完 ]

所以,只有当您指定一个获得作用域分配器行为scoped_allocator_adaptor作为分配器为您的容器。

如何做一个范围的分配使容器的实现大致从一个不知道作用域容器的不同?

关键在于,现在容器通过一个新的类称为其分配涉及allocator_traits ,而不是直接处理分配器。 和容器必须allocator_traits某些操作,如构建和破坏value_type容器秒。 容器必须不说话分配器直接。

例如,分配器提供构件称为construct将使用给定的参数在一定的地址构造类型:

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

如果分配不提供该会员, allocator_traits将提供一个默认的实现。 在任何情况下,容器必须构建所有value_type S使用此construct函数,但使用它通过allocator_traits ,而不是使用allocator直接:

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

scoped_allocator_adaptor提供自定义的construct哪些功能allocator_traits将转发给内搭的优势uses_allocator性状和沿该传递正确的分配器value_type构造。 容器仍然幸福无知的这些细节。 容器只知道它必须构建value_type使用allocator_traits construct函数。

还有更多细节,容器必须有应对正确处理状态分配器。 虽然这些细节也被具有容器不作任何假设,但得到通过的所有属性和行为处理allocator_traits 。 容器甚至不能假设pointerT* 。 相反这种类型被询问发现allocator_traits它是什么。

简而言之,建立一个C ++ 11容器中,在研究了allocator_traits 。 然后你得到免费范围的分配行为,当你的客户使用scoped_allocator_adaptor



Answer 2:

该类型由容器使用的分配是由它的构造函数的参数定义:正是这种类型的在容器中的构造函数的预期。 但是,任何分配需要能够比它定义为一个服务于不同的类型。 例如,对于一个std::list<T, A>分配器预期能够分配T对象,但它永远不会被用于分配这些对象,因为std::list<T, A>实际上需要分配节点。 即,分配器将被反弹至分配不同的类型。 不幸的是,这使得它很难使用分配器以服务于特定类型的:你不知道的分配实际上将服务类型。

对于作用域分配器它的工作原理相当简单:容器确定它是否有一个构造函数以匹配分配的任何成员。 如果是这样的话,它会重新绑定中使用的分配器,并将此分配器的构件。 什么不是直线前进是逻辑确定是否正在使用的分配器。 以确定是否成员使用的分配器,性状std::uses_allocator<T, A>使用:它确定是否T具有嵌套typedef allocator_type其中,如果A可以被转换成该类型。 为成员对象是如何构造的规则在20.6.7.2描述[allocator.uses.construction]。

在实践中,这意味着分配器是用于处理用于容器及其成员池有用。 在某些情况下也可能会在类似大小的物体被分配,例如用于任何节点基于容器,保持同等大小的对象池工作合理。 然而,没有必要明确从分配器使用,如果他们的模式,例如,对于包含与节点或一些字符串。 此外,由于使用不同的分配政策将改变类型,它要么默认分配棒或使用分配器类型这是实际定义该分配策略的多态分配的代理似乎是最合理的。 当然,你必须有状态的分配器的那一刻,你可能有不同的分配器和如对象swap()荷兰国际集团他们可能无法正常工作。



文章来源: STL Container: Constructor's Allocator parameter and scoped allocators