list位于头文件<<stl_list.h>>中node
list是sequence containers
中的一种c++
list的基本结构的UML关系图以下:架构
须要注意的是,向list中insert元素时,会构造一个真正的_List_node<_Tp>类型的_Node,将这个插入list当中;也就是说_List_node<_Tp>才是list中的真正元素函数
因为list的中的_list_node并不保证在内存空间中必定是连续的,因此list的迭代器并不能像vector之类的同样实现++或者- - 的操做,list的迭代器必须在++(或者 - -)时,必须正确的找到list中当前node的下一个位置(或者上一个位置)this
_List_iterator的自增与自减函数源码以下:设计
_Self& operator++() _GLIBCXX_NOEXCEPT { _M_node = _M_node->_M_next; return *this; } _Self operator++(int) _GLIBCXX_NOEXCEPT { _Self __tmp = *this; _M_node = _M_node->_M_next; return __tmp; } _Self& operator--() _GLIBCXX_NOEXCEPT { _M_node = _M_node->_M_prev; return *this; } _Self operator--(int) _GLIBCXX_NOEXCEPT { _Self __tmp = *this; _M_node = _M_node->_M_prev; return __tmp; }
能够看到,在++的重载中,都是经过_list_iterator中所存储_M_node来获取下一个_list_node的位置的(- -操做同理)指针
须要注意的是,list的iterator中指针_M_node的类型_List_node_base类型的,也就是说:在涉及到存取list节点中的数据时,须要向下转型为_List_node类型code
list其实不单单是一个双向链表,更是一个环形双向链表
,list中有一个_List_node_header类型的哑头节点,以下图所示内存
list的end()即是指向这个哑头节点的,begin()则是这个哑头节点的下一个节点源码
如下的函数都位于gcc/libstdc++-v3/src/c++98/list.cc
在insert的过程中就用到了这个函数,用来将新的节点链入到指定位置以前并保持list的完整性
该函数源码以下:
void _List_node_base:: _M_hook(_List_node_base* const __position) _GLIBCXX_USE_NOEXCEPT { this->_M_next = __position; this->_M_prev = __position->_M_prev; __position->_M_prev->_M_next = this; __position->_M_prev = this; }
顾名思义,该函数的做用是将某个节点从链表中卸下
源码以下:
void _List_node_base::_M_unhook() _GLIBCXX_USE_NOEXCEPT { _List_node_base* const __next_node = this->_M_next; _List_node_base* const __prev_node = this->_M_prev; __prev_node->_M_next = __next_node; __next_node->_M_prev = __prev_node; }
该函数的做用是将[__first, __last)之间的节点移动到另外一个位置
前半部分是调整_M_next指针
后半部分是调整_M_prev指针
该函数源码以下:
void _List_node_base:: _M_transfer(_List_node_base * const __first, _List_node_base * const __last) _GLIBCXX_USE_NOEXCEPT { if (this != __last) { // Remove [first, last) from its old position. __last->_M_prev->_M_next = this; __first->_M_prev->_M_next = __last; this->_M_prev->_M_next = __first; // Splice [first, last) into its new position. _List_node_base* const __tmp = this->_M_prev; this->_M_prev = __last->_M_prev; __last->_M_prev = __first->_M_prev; __first->_M_prev = __tmp; } }
该函数是内部函数,不对外暴露,可是list不少对外暴露的函数内部实现也是利用了_M_transfer函数,好比:merge
该函数是对外暴露的reverse()函数的内部调用函数
void _List_node_base::_M_reverse() _GLIBCXX_USE_NOEXCEPT { _List_node_base* __tmp = this; do { std::swap(__tmp->_M_next, __tmp->_M_prev); // Old next node is now prev. __tmp = __tmp->_M_prev; } while (__tmp != this); }
<