STL容器之list源碼詳細(xì)解讀
簡(jiǎn)介
相對(duì)于vector的連續(xù)線性空間,list就顯得更加復(fù)雜,它每插入或者刪除一個(gè)元素,就配置或釋放一個(gè)元素空間。
因此,list對(duì)于空間的利用非常精準(zhǔn),一點(diǎn)也不浪費(fèi),而且,對(duì)于任何位置的插入或者刪除,list永遠(yuǎn)是常數(shù)時(shí)間。
構(gòu)造函數(shù)
explicit list(const allocator_type& __a = allocator_type()) : _Base(__a) {} // 構(gòu)造擁有 n 個(gè)有值 value 的元素的容器 list(size_type __n, const _Tp& __value, const allocator_type& __a = allocator_type()) : _Base(__a) { insert(begin(), __n, __value); } explicit list(size_type __n) : _Base(allocator_type()) { insert(begin(), __n, _Tp()); } // 構(gòu)造擁有范圍 [first, last) 內(nèi)容的容器 list(const _Tp* __first, const _Tp* __last, const allocator_type& __a = allocator_type()) : _Base(__a) { this->insert(begin(), __first, __last); } list(const_iterator __first, const_iterator __last, const allocator_type& __a = allocator_type()) : _Base(__a) { this->insert(begin(), __first, __last); } // 拷貝構(gòu)造函數(shù) list(const list<_Tp, _Alloc>& __x) : _Base(__x.get_allocator()) { insert(begin(), __x.begin(), __x.end()); }
對(duì)于list中的每一個(gè)節(jié)點(diǎn),都被封裝成了_List_node對(duì)象:
// 雙向鏈表 struct _List_node_base { _List_node_base* _M_next; _List_node_base* _M_prev; }; // list 節(jié)點(diǎn) template <class _Tp> struct _List_node : public _List_node_base { _Tp _M_data; // 節(jié)點(diǎn)存儲(chǔ)的值 };
即list是通過雙向循環(huán)鏈表來組織節(jié)點(diǎn)的。
主要函數(shù)
push_back
void push_back(const _Tp& __x) { insert(end(), __x); } // 插入一個(gè)節(jié)點(diǎn),作為尾節(jié)點(diǎn) // 在__position之前插入節(jié)點(diǎn)__x iterator insert(iterator __position, const _Tp& __x) { _Node* __tmp = _M_create_node(__x); // 調(diào)整雙向指針,插入新元素 __tmp->_M_next = __position._M_node; // list為雙向鏈表 __tmp->_M_prev = __position._M_node->_M_prev; __position._M_node->_M_prev->_M_next = __tmp; __position._M_node->_M_prev = __tmp; return __tmp; }
push_back插入一個(gè)節(jié)點(diǎn),作為尾結(jié)點(diǎn),都是雙向鏈表的常用操作,這里不再贅述。
push_front
void push_front(const _Tp& __x) { insert(begin(), __x); } // 插入一個(gè)節(jié)點(diǎn) __x,作為頭結(jié)點(diǎn) iterator insert(iterator __position, const _Tp& __x) { _Node* __tmp = _M_create_node(__x); // 調(diào)整雙向指針,插入新元素 __tmp->_M_next = __position._M_node; // list為雙向鏈表 __tmp->_M_prev = __position._M_node->_M_prev; __position._M_node->_M_prev->_M_next = __tmp; __position._M_node->_M_prev = __tmp; return __tmp; }
push_front同樣是調(diào)用了insert(iterator, const _Tp&)來完成插入操作的。
clear
void clear() { _Base::clear(); } template <class _Tp, class _Alloc> void _List_base<_Tp,_Alloc>::clear() { _List_node<_Tp>* __cur = (_List_node<_Tp>*) _M_node->_M_next; // 指向開始節(jié)點(diǎn),begin() while (__cur != _M_node) { _List_node<_Tp>* __tmp = __cur; __cur = (_List_node<_Tp>*) __cur->_M_next; _Destroy(&__tmp->_M_data); // 銷毀(析構(gòu)并釋放)一個(gè)節(jié)點(diǎn) _M_put_node(__tmp); } // 恢復(fù) _M_node 原始狀態(tài) _M_node->_M_next = _M_node; _M_node->_M_prev = _M_node; }
clear時(shí)從頭結(jié)點(diǎn)到尾結(jié)點(diǎn),依次釋放每一個(gè)節(jié)點(diǎn)的內(nèi)存空間。
特點(diǎn)
由于list是通過雙向鏈表來實(shí)現(xiàn)的,它的迭代器要提供前移、后移的能力,所以list提供了Bidirectional iterator; 插入、刪除節(jié)點(diǎn)的效率很高。
與vector的區(qū)別
- vector為存儲(chǔ)的對(duì)象分配一塊連續(xù)的地址空間,隨機(jī)訪問效率很高。但是插入和刪除需要移動(dòng)大量的數(shù)據(jù),效率較低。尤其當(dāng)vector中存儲(chǔ)的對(duì)象較大,或者構(gòu)造函數(shù)復(fù)雜,則在對(duì)現(xiàn)有的元素進(jìn)行拷貝的時(shí)候會(huì)執(zhí)行拷貝構(gòu)造函數(shù)。
- list中的對(duì)象是離散的,隨機(jī)訪問需要遍歷整個(gè)鏈表,訪問效率比vector低。但是在list中插入元素,尤其在首尾插入,效率很高,只需要改變?cè)氐闹羔槨?/li>
- vector是單向的,而list是雙向的;
- 向量中的iterator在使用后就釋放了,但是鏈表list不同,它的迭代器在使用后還可以繼續(xù)用;鏈表特有的;
到此這篇關(guān)于STL容器之list源碼詳細(xì)解讀的文章就介紹到這了,更多相關(guān)STL容器list 內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
常用的C++標(biāo)準(zhǔn)庫頭文件小結(jié)
C++標(biāo)準(zhǔn)庫定義了一系列函數(shù)、宏和對(duì)象,以實(shí)現(xiàn)跨團(tuán)隊(duì)、跨平臺(tái)的高效且具有卓越性能的標(biāo)準(zhǔn)化 C++ 代碼, 本文介紹常用的C++標(biāo)準(zhǔn)庫頭文件,需要的朋友可以參考下2023-11-11C++ Coroutine簡(jiǎn)單學(xué)習(xí)教程
這篇文章主要為大家詳細(xì)介紹了C++ Coroutine的簡(jiǎn)單學(xué)習(xí)教程,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-08-08C/C++實(shí)現(xiàn)動(dòng)態(tài)數(shù)組的示例詳解
動(dòng)態(tài)數(shù)組相比于靜態(tài)數(shù)組具有更大的靈活性,因?yàn)槠浯笮】梢栽谶\(yùn)行時(shí)根據(jù)程序的需要?jiǎng)討B(tài)地進(jìn)行分配和調(diào)整,本文為大家介紹了C++實(shí)現(xiàn)動(dòng)態(tài)數(shù)組的方法,需要的可以參考下2023-08-08C語言中6組指針和自增運(yùn)算符結(jié)合方式的運(yùn)算順序問題
本文通過代碼實(shí)現(xiàn)分析了6種組合:* p++,(* p)++,* (p++),++* p,++( * p), * (++p),需要的朋友可以參考下2015-07-07深入理解C++中的new和delete并實(shí)現(xiàn)對(duì)象池
這篇文章主要介紹了C++中的new和delete并實(shí)現(xiàn)對(duì)象池,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-09-09