STL in C++11 (Allocator 2)

上篇文章學(xué)習(xí)了如何構(gòu)造容器后, 我們將學(xué)習(xí)如何析構(gòu)容器, 同時實現(xiàn)一些工具函數(shù)用于構(gòu)造與析構(gòu)铸抑。

首先創(chuàng)建一個頭文件"alloc_destroy.h"纱昧, 用來存放下面實現(xiàn)的構(gòu)造與析構(gòu)的工具函數(shù)

1.construct()

template<typename T1, typename T2>
void construct(T1 *p, const T2& value)
{
    new (p) T1(value);
}

我們先來活用之前學(xué)過的定位new運算符,實現(xiàn)construt()函數(shù)。construct()在指針p的位置調(diào)用構(gòu)造函數(shù)創(chuàng)建一個對象软舌,我們以后將使用construct()構(gòu)造單個對象。

2.destroy()

我們需要重載好幾個destroy()函數(shù)牛曹,先來看一個最簡單的

template<typename T>
void destroy(T *p)
{
    p->~T();
}

這個沒什么好說的佛点,在指針p所指位置調(diào)用析構(gòu)函數(shù)來釋放一個對象。但我們的容器一般都有多個元素黎比,肯定不能一個一個調(diào)用destroy(p)超营,那么我們肯定需要一個能直接析構(gòu)一個區(qū)間的destroy(begin, end):

template<typename ForwardIterator>
void destroy(ForwardIterator begin, ForwardIterator end)
{
    aux_destroy(begin, end, std::is_trivially_destructible<decltype(*begin)>());
}

template<typename ForwardIterator>
void aux_destroy(ForwardIterator begin, ForwardIterator end, std::true_type)
{
}


template<typename ForwardIterator>
void aux_destroy(ForwardIterator begin, ForwardIterator end, std::false_type)
{
    for (; begin != end; ++begin) {
        destroy(&*begin);
    }
}

對于沒深入了解過模板的人來說上面的代碼可能有點難以理解,但不要急阅虫,我們一步一步來演闭。
我們的目的是實現(xiàn)函數(shù) destroy(ForwardIterator begin, ForwardIterator end),我們先來看看它的內(nèi)部代碼:

aux_destroy(begin, end, std::is_trivially_destructible<decltype(*begin)>());

它調(diào)用了一個輔助函數(shù)aux_destroy颓帝,同時將區(qū)間參數(shù)向下傳遞米碰。但我們最迷惑的肯定是std::is_trivially_destructible<decltype(*begin)>()窝革,這的確有點復(fù)雜,我們可以從內(nèi)向外分解它吕座。

decltype(*begin): begin即得到迭代器begin所指的元素虐译, 而decltype()可以得到內(nèi)部元素的類型,合起來就是容器內(nèi)部元素的類型(因為begin的類型與容器內(nèi)其他元素的類型相同)吴趴。

std::is_trivially_destructible<T> : std::is_trivially_destructible是一個類模板漆诽,用來判斷類型T的析構(gòu)函數(shù)是否無關(guān)緊要(trivially)。那什么樣的類的析構(gòu)函數(shù)是trivial的锣枝?:

1. 使用隱式定義的析構(gòu)函數(shù)厢拭,即沒有定義自己析構(gòu)函數(shù)

2. 析構(gòu)函數(shù)不是虛函數(shù)

3. 其基類與非靜態(tài)成員也是可trivially析構(gòu)的

當(dāng)同時滿足上面3個條件時,我們就可稱類型T是 trivially_destructible

說了那么多撇叁, 我們來舉2個例子蚪腐。

class Test
{
private:
    int i;

public:
    Test(int i) { 
        this->i = i; 
    }
};

Test這個類就滿足之前的3個條件,所以它是trivially_destructible税朴。即我們調(diào)不調(diào)用析構(gòu)函數(shù)都無所謂回季,因為它本質(zhì)上并沒有任何需要釋放的資源。就像當(dāng)我們要釋放std::vector<int>類型的容器時正林,我們并不需要在意Int類型元素的釋放泡一,釋放vector<Test>也是一樣的道理。

再來看一個反例:

class Test
{
private:
    int i;
    int *p;

public:
    Test(int i) {
        this->i = i;
        p = new int;
    }

    ~Test() {
        delete p;
    }
};

很容易發(fā)現(xiàn)Test類現(xiàn)在多了一個指針變量p,并且p再構(gòu)造函數(shù)被賦值了觅廓。為了保證內(nèi)存不泄漏鼻忠,我們必須手動定義析構(gòu)函數(shù)釋放p。很顯然現(xiàn)在Test類已經(jīng)不是trivially destructible了杈绸,因為我們定義了自己的析構(gòu)函數(shù)帖蔓。此時它的析構(gòu)函數(shù)已經(jīng)不再無關(guān)緊要,因為必須要調(diào)用析構(gòu)函數(shù)來釋放內(nèi)存瞳脓。這個時候釋放std::vector<Test>對象時塑娇, 我們必須要為每個元素析構(gòu),這是庫作者必須要考慮到的事情劫侧。

進(jìn)一步埋酬, 當(dāng)T被判斷是trivially_destructible時, 類型std::is_trivially_destructible<T>將被推導(dǎo)為 std::true_type, 反之則為std::false_type烧栋。

std::is_trivially_destructible<decltype(*begin)>():
現(xiàn)在我們再來看是不是簡單了一點呢写妥? 這段代碼意思即為判斷元素類型是否是trivially_destructible。如果是审姓,類型被轉(zhuǎn)化為std::true_type珍特,反之std::false_type。 最后再調(diào)用構(gòu)造函數(shù)構(gòu)造出std::true_type或std::false_type的對象魔吐。

接下來就簡單了扎筒,編譯器將根據(jù)返回的是std::true_type還是std::false_type調(diào)用不同的輔助函數(shù)aux_destroy():

1. 當(dāng)參數(shù)為std::true_type時

可以看到我們的函數(shù)體為空呼猪,即我們什么都不做,因為類型的析構(gòu)函數(shù)無關(guān)痛癢砸琅,沒有任何影響宋距,只需系統(tǒng)自動回收

2.當(dāng)參數(shù)為std::false_type時

這時我們必須為每個元素調(diào)用構(gòu)造函數(shù)了,為此使用循環(huán)調(diào)用我們之前實現(xiàn)的destroy(T *p)症脂。

template<typename ForwardIterator>
void aux_destroy(ForwardIterator begin, ForwardIterator end, std::false_type)
{
    for (; begin != end; ++begin) {
        destroy(&*begin);
    }
}

終于谚赎,我們實現(xiàn)了想要的destroy(ForwardIterator begin, ForwardIterator end),它能夠幫助我們析構(gòu)[begin, end]范圍的所有元素。

好了诱篷,現(xiàn)在看看我們手上有了哪些工具:

1.

template<typename T1, typename T2>
void construct(T1 *p, const T2& value);

它可以幫助我們在p的位置上調(diào)用構(gòu)造函數(shù)

2.

template<typename T>
void destroy(T *p);

它能夠析構(gòu)p所指的對象

3.

template<typename ForwardIterator>
void destroy(ForwardIterator begin, ForwardIterator end);

它能夠析構(gòu)[begin, end)范圍的所有對象

我們接下來將運用這些函數(shù)壶唤,以及之后要講的分配器一起來實現(xiàn)容器的構(gòu)造與析構(gòu)。

好了棕所,這篇文章也到此結(jié)束啦闸盔。下一篇就真的要開始講Allocator,總算要進(jìn)入正題了琳省,真是不容易迎吵。不過Allocator的難度也很高,應(yīng)該要說很久针贬,還是請做好準(zhǔn)備吧击费。

最后附上本篇文章的代碼地址:https://github.com/Puppas/STL-in-Cpp11/blob/master/STL/alloc_destroy.h

以及github地址:https://github.com/Puppas/STL-in-Cpp11

下一篇 STL in C++11 Allocator 3

P.S 謝絕轉(zhuǎn)載,謝謝

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末桦他,一起剝皮案震驚了整個濱河市蔫巩,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌快压,老刑警劉巖粥鞋,帶你破解...
    沈念sama閱讀 221,273評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件岛蚤,死亡現(xiàn)場離奇詭異濒募,居然都是意外死亡吭产,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,349評論 3 398
  • 文/潘曉璐 我一進(jìn)店門拦宣,熙熙樓的掌柜王于貴愁眉苦臉地迎上來截粗,“玉大人,你說我怎么就攤上這事鸵隧。” “怎么了意推?”我有些...
    開封第一講書人閱讀 167,709評論 0 360
  • 文/不壞的土叔 我叫張陵豆瘫,是天一觀的道長。 經(jīng)常有香客問我菊值,道長外驱,這世上最難降的妖魔是什么育灸? 我笑而不...
    開封第一講書人閱讀 59,520評論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮昵宇,結(jié)果婚禮上磅崭,老公的妹妹穿的比我還像新娘。我一直安慰自己瓦哎,他們只是感情好砸喻,可當(dāng)我...
    茶點故事閱讀 68,515評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著蒋譬,像睡著了一般割岛。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上犯助,一...
    開封第一講書人閱讀 52,158評論 1 308
  • 那天癣漆,我揣著相機與錄音,去河邊找鬼剂买。 笑死惠爽,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的瞬哼。 我是一名探鬼主播疆股,決...
    沈念sama閱讀 40,755評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼倒槐!你這毒婦竟也來了旬痹?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,660評論 0 276
  • 序言:老撾萬榮一對情侶失蹤讨越,失蹤者是張志新(化名)和其女友劉穎两残,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體把跨,經(jīng)...
    沈念sama閱讀 46,203評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡人弓,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,287評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了着逐。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片崔赌。...
    茶點故事閱讀 40,427評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖耸别,靈堂內(nèi)的尸體忽然破棺而出健芭,到底是詐尸還是另有隱情,我是刑警寧澤秀姐,帶...
    沈念sama閱讀 36,122評論 5 349
  • 正文 年R本政府宣布慈迈,位于F島的核電站,受9級特大地震影響省有,放射性物質(zhì)發(fā)生泄漏痒留。R本人自食惡果不足惜谴麦,卻給世界環(huán)境...
    茶點故事閱讀 41,801評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望伸头。 院中可真熱鬧匾效,春花似錦、人聲如沸恤磷。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,272評論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽碗殷。三九已至精绎,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間锌妻,已是汗流浹背代乃。 一陣腳步聲響...
    開封第一講書人閱讀 33,393評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留仿粹,地道東北人搁吓。 一個月前我還...
    沈念sama閱讀 48,808評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像吭历,于是被迫代替她去往敵國和親堕仔。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,440評論 2 359