deque 即雙端佇列,與vector相比,此容器多出了pop_front()和push_front()這兩個操作,即在首部的增刪操作;而與list相比,deque多出了對容器元素的隨機訪問功能。
網上也有很多關於deque原始碼分析的文章,不過大部分都是繼承自侯捷《stl原始碼分析》中關於deque原始碼的講解。鮮有vs版本 stl deque原始碼的講解,現在就來看看vs版本是如何實現的。
若是讓我自己實現乙個簡單的deque,何不分配兩塊記憶體,一塊用來分配給push_back,另一塊分配給push_front,若是記憶體不夠了,就各自重新分配記憶體。插入或刪除操作,只需移動元素即可。然後分別記錄push_back與push_front的元素個數,這樣就可以隨機訪問了。我這個思路豈不是很簡單。
vs用到了二級指標,二級指標裡存放的一級指標是連續的,每乙個一級指標存放一塊記憶體的位址,這塊記憶體(就是陣列,連續的)存放的是我們push_back與push_front的元素。
假若把所有block中一級指標指向的記憶體看成連續的,那麼在這塊大記憶體中,一邊是push_back進來的,一邊是push_front進來的。
當然了,分界點,未必是0與31號記憶體,也可能是6,7號記憶體。(deque是模板類,若是模板引數是int,那麼二級指標就是int*)。
// template class _deque_val
templateclass _deque_val
: public _container_base12
;
在deque的基類,_deque_val中,有上面那幾個成員變數。_map就是二級指標,我們以deque用來存放int型元素舉例,那麼_map就是int**型別的變數。_mapsize就是一級指標數量,或者說用來存放我們元素的記憶體塊的數量。_myoff已經在圖2中標註,它就是我們第乙個元素的記憶體號,其實它就可以起到區分push_back元素與push_front元素的作用。_mysize就是deque中存在元素的數量。除了上面幾個成員變數還有兩個巨集,也很重要。
// deque parameters
#define _dequemapsiz 8 /* minimum map size, at least 1 */
#define _dequesiz (sizeof (value_type) <= 1 ? 16 \
: sizeof (value_type) <= 2 ? 8 \
: sizeof (value_type) <= 4 ? 4 \
: sizeof (value_type) <= 8 ? 2 \
: 1) /* elements per block (a power of 2) */
_dequemapsiz是_map最小的大小,_dequesiz是一級指標指向記憶體能分配元素的個數。這塊記憶體反正是16個位元組,那麼模板引數是int,那麼這個記憶體block就可以存放4個元素嘍。
當什麼時候需要增加一級指標的數量呢?當_myoff是4的倍數,並且元素數量<=容量減4 的時候,需要擴容了。
void _growmap(size_type _count)
else//情況2
//釋放push_front元素對應的block指標(一級指標)
_destroy_range(this->_map + _myboff, this->_map + this->_mapsize,
this->_almap);
//釋放二級記憶體_map
if (this->_map != 0)
this->_almap.deallocate(this->_map,
this->_mapsize); // free storage for old
this->_map = _newmap; // point at new
this->_mapsize += _count;
}
情況1:如圖3,當新分配記憶體大小,足以容納push_back元素
情況2:如圖4,當新分配記憶體大小,不 足以容納push_back元素,這時候就需要往分批拷貝。
push_back用到了兩個巨集_push_back_begin與_push_back_end,貼上**直接把巨集替換掉了。
void push_back(_ty&& _val)
push_front用到了兩個巨集_push_front_begin與_push_front_end,貼上**直接把巨集替換掉了。
void push_front(_ty&& _val)
迭代器裡面只有乙個成員變數,_myoff,即 offset of element in deque,意思就是相對於0號記憶體的位置,即記憶體號。假如現在有8個block,每個block容納4個元素,push_front了21次,那麼begin()返回的迭代器的_myoff應該為32-21==11。11號記憶體位置存放著我們第乙個元素。只有_myoff++就相當於迭代器++,就可以檢視後面那個記憶體了。
// template class _deque_const_iterator
templateclass _deque_const_iterator
: public _iterator_base12
;
iterator erase(const_iterator _first_arg,
const_iterator _last_arg)
else
return (begin() + _off);
}
VS2010 rdlc報表 不在依賴 資料來源
在傳統的vs2005與vs2008中,rdlc報表是必須依賴外在的資料集的,但是vs2010 rdlc 報表不在需要外在資料集,關鍵是因為rdlc報表 內建了乙個資料集,把rdlc報表 用xml方式開啟,自己可以按照xml的方式 設定乙個資料集如下方式,其中紅色的部分為多餘的部分,可以去掉.stco...
如何提高VS2010的效能,VS2010不再卡
教大家幾個技巧可以稍微讓你覺得它沒那麼卡!一 vs2010選項視覺體驗設定 工具 選項 環境 視覺體驗的勾選都去掉。不解釋,你懂得。不過還是建議開啟硬體加速 二 禁用intellisense 工具 選項 文字編輯器 c c 高階 禁用intellisense設為true 這個功能很好用。相較於vis...
Matlab R2010a和vs 2010混合程式設計
matlabr2010a與vs2010 c 混合程式設計成功,在vs2010 c 中能夠呼叫matlab的m函式,進行計算,得到正確結果,呼叫matlab中m函式轉化成的dll檔案 一 matlab編譯環境的設定 mex setup pleasechoose your compiler for bu...