C++ 标准容器如何为其节点(内部结构)分配内存?
例如,如果std::set和std::map具有类型为的分配器,我无法理解它们如何为节点分配内存C++ 标准容器如何为其节点(内部结构)分配内存?,c++,C++,例如,如果std::set和std::map具有类型为的分配器,我无法理解它们如何为节点分配内存 std::allocator<Key> std::分配器 及 std::分配器 分别。据我猜测,在std::set中应该有这样的代码,例如: std::pair<iterator, bool> insert(const value_type& value) { ... Node * node = new Node(); node->
std::allocator<Key>
std::分配器
及
std::分配器
分别。据我猜测,在std::set中应该有这样的代码,例如:
std::pair<iterator, bool> insert(const value_type& value)
{
...
Node * node = new Node();
node->value = value;
...
return InsertNode(node);
}
std::成对插入(常量值\u类型和值)
{
...
Node*Node=新节点();
节点->值=值;
...
返回InsertNode(node);
}
或
std::成对插入(常量值\u类型和值)
{
...
Node*Node=新节点();
节点->p_值=a1.分配(1);
*(节点->p_值)=值;
...
返回InsertNode(node);
}
其中节点是一些内部结构,例如红黑树节点
所以问题是这个节点的内存是如何分配的?您提供的分配器将恢复到节点结构的类型,然后用于分配节点 <> >代码> STD::分配器< /C>(默认)将调用<代码>运算符new <代码>,然后执行特定于实现的操作(通常调用<代码> MalOC )。C++中的(< / P> < P>分配器)(由于某种原因)将被键入。也就是说,特定的分配器类实例分配特定类型的对象 但是,由于容器可能需要分配的实际类型可能不同于容器的值类型(容器逻辑上包含的类型),因此分配器(主要)需要能够转换为分配任何其他类型对象的备用分配器实例。这个过程称为“重新绑定”,它是通过调用
allocator.rebind
启动的,其中U
是系统想要实际分配的类型
新的分配器实例是原始分配器的反弹形式,必须从与原始分配器相同的内存池中进行分配。因此,重新绑定被视为基于类型的更改,而不是真正不同的对象
标准库容器的实现不允许使用new
或delete
;必须通过分配器执行分配内存中的所有动态取消/分配和对象创建/销毁
当
std::set
插入一个项时,它会将您的分配器重新绑定到某个节点类型,该节点类型内部包含T
本身或足够正确对齐的存储,以便在其中创建T
。然后,它将使用分配器接口创建该节点类型,并初始化它包含的T
std::map
有点复杂,但本质上它的节点类型必须存储一个键
和一个值
它们是如何“反弹”的?什么分配器方法用于此目的?@AlexeyStarinsky-See。大致上,容器使用NodeAllocator=typename allocator::template rebind重新绑定分配器,类似于,它可以从原始分配器构造(根据所需的有效表达式A(b)
)。所以他们可以转换它:NodeAllocator-NodeAllocator(分配器)
请澄清一下,std::set是否允许客户端提供NodeAllocator实例,就像分配器允许将其实例作为构造函数参数传递一样?NodeAllocator可能是这样创建的NodeAllocator nodeAlloc(alloc);alloc是分配器实例。我不太明白你的问题是什么——你不清楚内存分配过程是什么?正如答案所解释的,allocator::allocate
在某个点被调用,它调用操作符new
,它执行malloc
。您是否想知道在allocate()
或其返回值之前会发生什么,或者您是在问malloc()
是如何工作的?@Chronial我不是问std::allocator是如何实现的,而是问std::set是如何实现的。它如何使用分配器分配键和节点,而分配器::allocate()返回类型是Key*?allocator.rebind
在C++17中被弃用,现在有了std::allocator\u traits::template rebind\u alloc
@AlexeyStarinsky为什么不能使用std::allocator\u traits::rebind\u alloc
?模板
是必要的吗?@zjyhjqs:是的,模板
是必要的。编译器需要知道依赖名称rebind\u alloc
是否为模板。毕竟,编译器不知道它是否应该解释@nicolasbolas,我仍然不明白模板
为什么连接在std::allocator\u traits
后面?我以前没见过这样的语法,你能给我一些参考资料,甚至一些关键字吗。谢谢。@Nicolas,我也不知道如何使用它。例如,对于类型T
,我有一个树节点类型TreeNode
,还有一个分配器allocator
。我是否应该编写std::allocator\u traits::template rebind\u traits
?
std::pair<iterator, bool> insert(const value_type& value)
{
...
Node * node = new Node();
node->value = value;
...
return InsertNode(node);
}
std::pair<iterator, bool> insert(const value_type& value)
{
...
Node * node = new Node();
node->p_value = a1.allocate(1);
*(node->p_value) = value;
...
return InsertNode(node);
}