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); }
<