繁体   English   中英

C ++中的分配器用法(STL树)

[英]Allocator usage in C++ (STL Tree)

我最近一直试图理解c ++分配器是如何工作的,我一直在寻找STL库用于std::setstd::map类的红黑树的实现,但是有一些我无法理解的事情。

首先要做的是将分配器从容器必须存储的类型 - _Val - 转换为树使用的节点类型 - _Rb_tree_node<_Val> - 使用重新绑定模板:

typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template
    rebind<_Rb_tree_node<_Val> >::other _Node_allocator;

typedef __gnu_cxx::__alloc_traits<_Node_allocator> _Alloc_traits;

我可以解决这个问题。

现在,当插入一个元素并且需要创建一个新节点时,它的作用就是这个

_Node_type __node = _Alloc_traits::allocate(_M_get_Node_allocator(), 1);

我假设为单个节点分配空间。 但是它就是这样做的

::new(__node) _Rb_tree_node<_Val>;

我真的不知道它做了什么,因为__node的空间已经被分配了。 但在此之后它也会这样做

_Alloc_traits::construct(_M_get_Node_allocator(), __node->_M_valptr(), ...);

这让我更加困惑,因为它应该构建一个节点(是节点分配器),但它传递指针__node->_M_valptr() ,它是_Val*类型。

如果有人能够解释这一点,我将非常感激。

::new(__node) _Rb_tree_node<_Val>;

这种新表达形式称为“放置新”。 它不分配新内存,而只构造参数指向的内存区域中的对象。 这里__node是指向已经为节点分配的内存的指针,该表达式在这个地方构造一个_Rb_tree_node<_Val>类型的对象。

_Alloc_traits::construct(_M_get_Node_allocator(), __node->_M_valptr(), ...);

此行在__node->_M_valptr()指向的内存中构造 _Val类型的对象。

这条线

::new(__node) _Rb_tree_node<_Val>;

使用placement new ,它只是在给定的内存地址__node)构造一个_Rb_tree_node<_Val>类型的对象。 这构造了节点对象。

现在它需要与_M_valptr()一个成员做一些事情。 这条线

_Alloc_traits::construct(_M_get_Node_allocator(), __node->_M_valptr(), ...);

(间接调用)分配器的construct方法 ,它非常类似于全局布局new (事实上​​,它通常只是调用它)。 因此,它再次获取指向构造对象的位置的指针。 这构造了值对象。

它使用了一种名为“ Placement New ”的东西,它允许在已经分配的内存中构造一个对象。

void * mem = malloc(sizeof(MyStruct));
MyStruct * my_struct_ptr = new(mem) MyStruct(/*Args...*/);

/*Do stuff...*/

my_struct_ptr->~MyStruct();//Literally one of the only times a good programmer would ever do this!
free(mem);

或者你可以像这样写:

char * mem = new char[sizeof(MyStruct)];
MyStruct * my_struct_ptr = new(mem) MyStruct(/*Args...*/);

/*Do stuff...*/

my_struct_ptr->~MyStruct();//Literally one of the only times a good programmer would ever do this!
delete mem;

或这个:

char mem[sizeof(MyStruct)];
MyStruct * my_struct_ptr = new(mem) MyStruct(/*Args...*/);

/*Do stuff...*/

my_struct_ptr->~MyStruct();//Literally one of the only times a good programmer would ever do this!

基本思想是,您现在负责通常由语言和编译器自动处理的手动清理。 在使用分配器时, 除了内存分配的直接控制对于编写好的分配器至关重要,这是非常糟糕的做法。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM