C++ deque與vector對比的優(yōu)缺點(diǎn)
deque容器
deque與vector十分的相識。vector是單向開口的連續(xù)線性空間(單向擴(kuò)容),deque則是一種雙向開口的連續(xù)線性空間(雙向擴(kuò)容)。雙向開口:可以在頭尾兩端分別做元素的插入和刪除操作。區(qū)別就在此,vector當(dāng)然也可以在頭尾兩端進(jìn)行操作,但是其頭部操作的效率奇差,無法被接受,如:stack與queue的容量適配器就在二者其中,選擇deque(當(dāng)然使用vector也可)。
vector與deque的差異:
- deque允許于常數(shù)時間內(nèi)對頭端進(jìn)行元素的插入或移除操作。
- deque沒有所謂的容量觀念,因為它是動態(tài)地以分段連續(xù)空間組合而成,隨時可以增加一段新的空間并連接起來。
與stack相比deque的優(yōu)缺點(diǎn):
優(yōu)勢:
- 頭尾插入刪除很方便
劣勢:
- operator[]計算稍顯復(fù)雜,大量使用,性能下降(下標(biāo)需要經(jīng)過計算)。
- 中間插入刪除效率不高(下標(biāo)需要經(jīng)過計算,并且需要挪動元素)。
- 底層角度迭代器會很復(fù)雜。
結(jié)論:
- 頭尾的插入刪除deque非常適合,相比vector而言,很適合去做stack和queue的默認(rèn)適配容器。
- 中間插入刪除少用deque,可以用:list(因為無需挪動元素)。
- 隨機(jī)訪問多用vector(因為下標(biāo)是確定的)。
deque的迭代器
需要注意,deque是連續(xù)的空間,但是這只是其邏輯上的,物理上并不是。所以在迭代器上維持其“整體連續(xù)”假象的工作,就落在迭代器中的operator++與operator--上了。
首先,連續(xù)重要的就是能夠指出分段空間在哪里,其次,它必須能夠判斷自己是否已經(jīng)處于其所在的存儲邊緣,如果是,一旦前行或后退時就必須跳躍到下一個或上一個存儲空間。
// __deque_iterator的源碼 template <class T, class Ref, class Ptr, size_t BufSiz> struct __deque_iterator { typedef __deque_iterator<T, T&, T*> iterator; typedef __deque_iterator<T, const T&, const T*> const_iterator; static size_t buffer_size() {return __deque_buf_size(0, sizeof(T)); }//buffer_size()用于確定緩沖區(qū)的大小 typedef random_access_iterator_tag iterator_category; typedef T value_type; typedef Ptr pointer; typedef Ref reference; typedef size_t size_type; // size_t 是unsigned 類型,通常用來指明數(shù)組長度 typedef ptrdiff_t difference_type; // ptrdiff_t 是 signed 整型,通常用來保存兩個指針減法操作的結(jié)果 typedef T** map_pointer; typedef __deque_iterator self; // 保持與容器的聯(lián)結(jié),是對某一個緩沖區(qū)而言的 T* cur; // 此迭代器所指之緩沖區(qū)中的現(xiàn)行元素 T* first; // 此迭代器所指之緩沖區(qū)的頭 T* last; // 此迭代器所指之緩沖區(qū)的尾(含備用空間) map_pointer node; // 指向管控中心 ... } //deque_buf_size()全局函數(shù) inline size_t deque_buf_size(size_t n, size_t sz){ return n != 0 ? n : (sz < 512 ? size_t(512 / sz) : size_t(1)); } //定義: //1. 如果n不為0,傳回n,表示buffer size由使用者自定。 //2. 如果n為0,表示buffer size使用默認(rèn)值,那么: // 如果sz不小于 512,返回1。 // 如果sz(元素大小,sizeof(value_type))小于512,傳回512/sz。
void set_node(map_pointer new_node) { node = new_node; first = *new_node; last = first + difference_type(buffer_size()); } reference operator*() const { return *cur; } pointer operator->() const { return &(operator*()); } difference_type operator-(const self& x) const { return difference_type(buffer_size()) * (node - x.node - 1) + (cur - first) + (x.last - x.cur); } self& operator++() { ++cur; //切換至下個元素 if (cur == last) { //如果已達(dá)所在緩沖區(qū)的尾端,就切換至下一節(jié)點(diǎn)(亦即緩沖區(qū))的第一個元素 set_node(node + 1); cur = first; } return *this; } self operator++(int) { //后置式,標(biāo)準(zhǔn)寫法 self tmp = *this; ++*this; return tmp; } self& operator--() { if (cur == first) {//如果已達(dá)所在緩沖區(qū)的頭端, 就切換至前一節(jié)點(diǎn)(亦即緩沖區(qū))的最后一個元素 set_node(node - 1); cur = last; } --cur; //切換至前一個元素 return *this; } self operator--(int) { //后置式,標(biāo)準(zhǔn)寫法 self tmp = *this; --*this; return tmp; } // 以下實(shí)現(xiàn)隨機(jī)存取。迭代器可以直接跳躍n個距離 self& operator+=(difference_type n) { difference_type offset = n + (cur - first); if (offset >= 0 && offset < difference_type(buffer_size())) //標(biāo)的位置在同一緩沖區(qū)內(nèi) cur += n; else { //標(biāo)的位置不在同一緩沖區(qū)內(nèi) difference_type node_offset = offset > 0 ? offset / difference_type(buffer_size()) : -difference_type((-offset - 1) / buffer_size()) - 1; // 切換至正確的節(jié)點(diǎn)(亦即緩沖區(qū)) set_node(node + node_offset); // 切換至正確的元素 cur = first + (offset - node_offset * difference_type(buffer_size())); } return *this; } self operator+(difference_type n) const { self tmp = *this; return tmp += n; //調(diào)用operator+= } //利用operator+=完成operator-= self& operator-=(difference_type n) { return *this += -n; } self operator-(difference_type n) const { self tmp = *this; return tmp -= n; //調(diào)用operator-= } //實(shí)現(xiàn)隨機(jī)存取,迭代器可以直接跳躍n個距離 reference operator[] (difference_type n) const { return * (*this + n);)} bool operator==(const self& x) const { return cur == x.cur; } bool operator!=(const self& x) const { return !(*this == x); } bool operator<(const self& x) const { return (node == x.node) ? (cur < x.cur) : (node < x.node); }
deque的成員函數(shù)
函數(shù)成員 | 函數(shù)功能 |
---|---|
begin() | 返回指向容器中第一個元素的迭代器。 |
end() | 返回指向容器最后一個元素所在位置后一個位置的迭代器,通常和 begin() 結(jié)合使用。 |
rbegin() | 返回指向最后一個元素的迭代器。 |
rend() | 返回指向第一個元素所在位置前一個位置的迭代器。 |
cbegin() | 和 begin() 功能相同,只不過在其基礎(chǔ)上,增加了 const 屬性,不能用于修改元素。 |
cend() | 和 end() 功能相同,只不過在其基礎(chǔ)上,增加了 const 屬性,不能用于修改元素。 |
crbegin() | 和 rbegin() 功能相同,只不過在其基礎(chǔ)上,增加了 const 屬性,不能用于修改元素。 |
crend() | 和 rend() 功能相同,只不過在其基礎(chǔ)上,增加了 const 屬性,不能用于修改元素。 |
size() | 返回實(shí)際元素個數(shù)。 |
max_size() | 返回容器所能容納元素個數(shù)的最大值。這通常是一個很大的值,一般是 232-1,我們很少會用到這個函數(shù)。 |
resize() | 改變實(shí)際元素的個數(shù)。 |
empty() | 判斷容器中是否有元素,若無元素,則返回 true;反之,返回 false。 |
shrink _to_fit() | 將內(nèi)存減少到等于當(dāng)前元素實(shí)際所使用的大小。 |
at() | 使用經(jīng)過邊界檢查的索引訪問元素。 |
front() | 返回第一個元素的引用。 |
back() | 返回最后一個元素的引用。 |
assign() | 用新元素替換原有內(nèi)容。 |
push_back() | 在序列的尾部添加一個元素。 |
push_front() | 在序列的頭部添加一個元素。 |
pop_back() | 移除容器尾部的元素。 |
pop_front() | 移除容器頭部的元素。 |
insert() | 在指定的位置插入一個或多個元素。 |
erase() | 移除一個元素或一段元素。 |
clear() | 移出所有的元素,容器大小變?yōu)?0。 |
swap() | 交換兩個容器的所有元素。 |
emplace() | 在指定的位置直接生成一個元素。 |
emplace_front() | 在容器頭部生成一個元素。和 push_front() 的區(qū)別是,該函數(shù)直接在容器頭部構(gòu)造元素,省去了復(fù)制移動元素的過程。 |
emplace_back() | 在容器尾部生成一個元素。和 push_back() 的區(qū)別是,該函數(shù)直接在容器尾部構(gòu)造元素,省去了復(fù)制移動元素的過程。 |
到此這篇關(guān)于C++ deque與vector對比的優(yōu)缺點(diǎn)的文章就介紹到這了,更多相關(guān)C++ deque與vector內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++實(shí)現(xiàn)LeetCode(81.在旋轉(zhuǎn)有序數(shù)組中搜索之二)
這篇文章主要介紹了C++實(shí)現(xiàn)LeetCode(81.在旋轉(zhuǎn)有序數(shù)組中搜索之二),本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-07-07C語言實(shí)現(xiàn)刪除某一個數(shù)組值的方法
這篇文章主要給大家分享C語言數(shù)組中刪除數(shù)組中某個值的方法,既然要學(xué)習(xí)刪除數(shù)組中的元素,我們就必須得先知道數(shù)組中有哪些元素。同時還要定義一個變量,并將需要刪除的元素賦值給那個變量。下面來看看文章的詳細(xì)內(nèi)容吧2021-11-11C語言實(shí)現(xiàn)將double/float 轉(zhuǎn)為字符串(帶自定義精度)
這篇文章主要介紹了C語言實(shí)現(xiàn)將double/float 轉(zhuǎn)為字符串(帶自定義精度),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-12-12C++??STL?_?Vector使用及模擬實(shí)現(xiàn)
這篇文章主要介紹了C++ STL_Vector使用及模擬實(shí)現(xiàn),文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價值,需要的小伙伴可以參考一下2022-08-08