[英]Allocator usage in C++ (STL Tree)
我最近一直试图理解c ++分配器是如何工作的,我一直在寻找STL库用于std::set
或std::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>;
使用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.