我最近一直在尝试理解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*
类型。
如果有人能解释一下这个问题,我会非常感激。
operator new
并不是分配内存,而是创建一个对象(有时也会分配内存,但在这种情况下不会)。因此,我认为第二行 (::new(__node) _Rb_tree_node<_Val>;
) 可能会在__node
分配的内存块中构造节点。 - alexeykuzmin0__node
传递给运算符?此外,如果它确实构造了节点,那么::construct()
之后会发生什么? - gmardaunew
语法。否则,它怎么知道在哪里放置new
对象呢? - underscore_d