欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C++中allocator類使用示例

 更新時(shí)間:2022年02月10日 15:39:40   作者:戀戀風(fēng)辰  
大家好,本篇文章主要講的是C++中allocator類使用示例,感興趣的同學(xué)趕快來看一看吧,對(duì)你有幫助的話記得收藏一下

動(dòng)態(tài)內(nèi)存管理

之前我們講述過動(dòng)態(tài)內(nèi)存的開辟,可以通過new, malloc,以及alloc等方式,本文通過介紹alloc方式,構(gòu)造一個(gè)StrVec類,這個(gè)類的功能類似于一個(gè)vector,實(shí)現(xiàn)字符串的管理,其中包含push一個(gè)字符串,動(dòng)態(tài)擴(kuò)容,析構(gòu),回收內(nèi)存等操作。

StrVec類實(shí)現(xiàn)細(xì)節(jié)

StrVec類實(shí)現(xiàn)如下

class StrVec
{
public:
    //無參構(gòu)造函數(shù)
    StrVec() : elements(nullptr), first_free(nullptr),
               cap(nullptr) {}
    //拷貝構(gòu)造函數(shù)
    StrVec(const StrVec &);
    //拷貝賦值運(yùn)算符
    StrVec &operator=(const StrVec &);
    //析構(gòu)函數(shù)
    ~StrVec();
    //拷貝元素
    void push_back(const std::string &);
    //返回元素個(gè)數(shù)
    size_t size() const { return first_free - elements; }
    //返回總?cè)萘?
    size_t capacity() const { return cap - elements; }
    //返回首元素地址
    std::string *begin() const
    {
        return elements;
    }
    //返回第一個(gè)空閑元素地址
    //也是最后一個(gè)有效元素的下一個(gè)位置
    std::string *end() const
    {
        return first_free;
    }

private:
    //判斷容量不足開辟新空間
    void chk_n_alloc()
    {
        if (size() == capacity())
            reallocate();
    }
    //重新開辟空間
    void reallocate();
    // copy指定范圍的元素到新的內(nèi)存中
    std::pair<std::string *, std::string *> alloc_n_copy(
        const std::string *, const std::string *);
    //釋放空間
    void free();
    //數(shù)組首元素的指針
    std::string *elements;
    //指向數(shù)組第一個(gè)空閑元素的指針
    std::string *first_free;
    //指向數(shù)組尾后位置的指針
    std::string *cap;
    //構(gòu)造string類型allocator靜態(tài)成員
    static std::allocator<std::string> alloc;
};

1 elements成員,該成員指向StrVec內(nèi)部數(shù)組空間的第一個(gè)元素
2 first_free成員指向第一個(gè)空閑元素,也就是有效元素的下一個(gè)元素,該元素開辟空間但未構(gòu)造。
3 cap 指向最后一個(gè)元素的下一個(gè)位置。
4 alloc為靜態(tài)成員,主要負(fù)責(zé)string類型數(shù)組的開辟工作。
5 無參構(gòu)造函數(shù)將三個(gè)指針初始化為空,并且默認(rèn)夠早了alloc。
6 alloc_n_copy私有函數(shù)的功能是將一段區(qū)域的數(shù)據(jù)copy到新的空間,
并且返回新開辟的空間地址以及第一個(gè)空閑元素的地址(第一個(gè)未構(gòu)造元素的地址)。
7 chk_n_alloc私有函數(shù)檢測(cè)數(shù)組大小是否達(dá)到容量,如果達(dá)到則調(diào)用reallocate重新開辟空間。
8 reallocate重新開辟空間
9 capacity返回總?cè)萘?br />10 size返回元素個(gè)數(shù)
11 push_back 將元素放入開辟的類似于數(shù)組的連續(xù)空間中。
12 begin返回首元素地址
13 end返回第一個(gè)空閑元素地址,也是最后一個(gè)有效元素的下一個(gè)位置
無論我們實(shí)現(xiàn)push操作還是拷貝構(gòu)造操作,都要實(shí)現(xiàn)realloc,當(dāng)空間不足時(shí)要開辟空間將舊數(shù)據(jù)移動(dòng)到新的數(shù)據(jù)

//重新開辟空間
void StrVec::reallocate()
{
    string *newdata = nullptr;
    //數(shù)組為空的情況
    if (elements == nullptr || cap == nullptr || first_free == nullptr)
    {
        newdata = alloc.allocate(1);
        // elements和first_free都指向首元素
        elements = newdata;
        first_free = newdata;
        // cap指向數(shù)組尾元素的下一個(gè)位置。
        cap = newdata + 1;
        return;
    }
    //不為空則擴(kuò)充兩倍空間
    newdata = alloc.allocate(size() * 2);
    //新內(nèi)存空閑位置
    auto dest = newdata;
    //舊內(nèi)存有效位置
    auto src = elements;
    //通過移動(dòng)操作將舊數(shù)據(jù)放到新內(nèi)存中
    for (size_t i = 0; i != size(); ++i)
    {
        alloc.construct(dest++, std::move(*src++));
    }
    //移動(dòng)后舊內(nèi)存數(shù)據(jù)無效,一定要?jiǎng)h除
    free();
    //更新數(shù)據(jù)位置
    elements = newdata;
    //更新第一個(gè)空閑位置
    first_free = dest;
    //更新容量
    cap = elements + size() * 2;
}

reallocate函數(shù)內(nèi)部判斷是否為剛初始化指針卻沒開辟空間的空數(shù)組,如果是則開辟1個(gè)大小的空間。
否則則開辟原有空間的兩倍,將舊數(shù)據(jù)移動(dòng)到新空間,采用了std::move操作,這么做減少拷貝造成的性能開銷。
move之后原數(shù)據(jù)就無效了,所以要調(diào)用私有函數(shù)free()進(jìn)行釋放。我們實(shí)現(xiàn)該free操作

//釋放操作
void StrVec::free()
{
    //判斷elements是否為空
    if (elements == nullptr)
    {
        return;
    }

    auto dest = elements;
    //要先遍歷析構(gòu)每一個(gè)對(duì)象
    for (size_t i = 0; i < size(); i++)
    {
        // destroy會(huì)調(diào)用每一個(gè)元素的析構(gòu)函數(shù)
        alloc.destroy(dest++);
    }
    //再整體回收內(nèi)存
    alloc.deallocate(elements, cap - elements);
}

先通過遍歷destroy銷毀內(nèi)存,從而調(diào)用string的析構(gòu)函數(shù),最后在deallocate回收內(nèi)存。

// copy指定范圍的元素到新的內(nèi)存中,返回新元素的地址和第一個(gè)空閑元素地址的pair
std::pair<std::string *, std::string *> StrVec::alloc_n_copy(
    const std::string *b, const std::string *e)
{
    auto newdata = alloc.allocate(e - b);
    //將原數(shù)據(jù)用來初始化新空間
    auto first_free = uninitialized_copy(b, e, newdata);
    return {newdata, first_free};
}

這樣利用alloc_n_copy,我們就可以實(shí)現(xiàn)拷貝構(gòu)造和拷貝賦值了

//拷貝構(gòu)造函數(shù)
StrVec::StrVec(const StrVec &strtmp)
{
    //將形參數(shù)據(jù)拷貝給自己
    auto rsp = alloc_n_copy(strtmp.begin(), strtmp.end());
    //更新elements, cap,first_free
    elements = rsp.first;
    first_free = rsp.second;
    cap = rsp.second;
}

但是拷貝賦值要注意一點(diǎn),就是自賦值的情況,所以我們提前判斷是否為自賦值,如不是則進(jìn)行和拷貝構(gòu)造相同的操作

//拷貝賦值運(yùn)算符
StrVec &StrVec::operator=(const StrVec &strtmp)
{
    //防止自賦值
    if (this == &strtmp)
    {
        return *this;
    }
    //將形參數(shù)據(jù)拷貝給自己
    auto rsp = alloc_n_copy(strtmp.begin(), strtmp.end());
    //更新elements, cap,first_free
    elements = rsp.first;
    first_free = rsp.second;
    cap = rsp.second;
}

我們可以利用free實(shí)現(xiàn)析構(gòu)函數(shù)

//析構(gòu)
StrVec::~StrVec()
{
    free();
}

接下來我們實(shí)現(xiàn)push_back,將指定字符串添加到數(shù)組空間,以及拋出元素

//添加元素
void StrVec::push_back(const std::string &s)
{
    chk_n_alloc();
    alloc.construct(first_free++, s);
}

//拋出元素
void StrVec::pop_back(std::string &s)
{
    if (first_free == nullptr)
    {
        return;
    }

    if (size() == 1)
    {
        
        s = *elements;
        alloc.destroy(elements);
        first_free = nullptr;
        elements = nullptr;
        return;
    }

    s = *(--first_free);
    alloc.destroy(first_free);
}

接下來實(shí)現(xiàn)測(cè)試函數(shù),測(cè)試上述操作

void test_strvec()
{
    auto str1 = StrVec();
    str1.push_back("hello zack");
    StrVec str2(str1);
    str2.push_back("hello rolin");
    StrVec str3 = str1;
    string strtmp;
    str3.pop_back(strtmp);
}

在主函數(shù)調(diào)用上面test_strvec,運(yùn)行穩(wěn)定。

總結(jié)

本文通過allocator實(shí)現(xiàn)了一個(gè)類似于vector的類,管理string變量。演示了拷貝構(gòu)造,拷貝賦值要注意的事項(xiàng),同時(shí)演示了如何手動(dòng)開辟內(nèi)存并管理內(nèi)存空間。

到此這篇關(guān)于C++中allocator類使用示例的文章就介紹到這了,更多相關(guān)C++ allocator類內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C++輸入輸出重定向方法示例

    C++輸入輸出重定向方法示例

    這篇文章主要給大家介紹了關(guān)于C++輸入輸出重定向的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2018-09-09
  • C++多線程中互斥量的使用詳解

    C++多線程中互斥量的使用詳解

    這篇文章主要介紹了C++多線程中互斥量的使用,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-08-08
  • C++計(jì)數(shù)排序詳解

    C++計(jì)數(shù)排序詳解

    計(jì)數(shù)排序的思想我們之前接觸過的例如:插入排序,歸并排序,快速排序,堆排序等都是基于集合元素之間的比較這一基本的思想,它們執(zhí)行的時(shí)間復(fù)雜度最優(yōu)是趨于O(nlgn),而計(jì)數(shù)排序的運(yùn)行機(jī)制不是基于集合元素之間的大小比較
    2016-04-04
  • C++多線程中的鎖和條件變量使用教程

    C++多線程中的鎖和條件變量使用教程

    這篇文章主要介紹了C++多線程中的鎖和條件變量使用,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2018-11-11
  • C語言中定義與聲明有哪些區(qū)別

    C語言中定義與聲明有哪些區(qū)別

    在C/C++中有一個(gè)基礎(chǔ)且重要的知識(shí),什么是聲明?什么是定義?他們的區(qū)別是什么?本文將帶你理清其中的區(qū)別
    2022-07-07
  • C語言實(shí)現(xiàn)停車場(chǎng)管理

    C語言實(shí)現(xiàn)停車場(chǎng)管理

    這篇文章主要為大家詳細(xì)介紹了C語言課程設(shè)計(jì)之停車場(chǎng)管理問題,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-12-12
  • C語言中求余運(yùn)算符的使用解讀

    C語言中求余運(yùn)算符的使用解讀

    這篇文章主要介紹了C語言中求余運(yùn)算符的使用,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-02-02
  • c++動(dòng)態(tài)內(nèi)存管理與智能指針的相關(guān)知識(shí)點(diǎn)

    c++動(dòng)態(tài)內(nèi)存管理與智能指針的相關(guān)知識(shí)點(diǎn)

    為了更容易同時(shí)也更安全地使用動(dòng)態(tài)內(nèi)存,新的標(biāo)準(zhǔn)庫提供了兩種智能指針(smart pointer)類型來管理對(duì)象,下面這篇文章主要給大家介紹了關(guān)于c++動(dòng)態(tài)內(nèi)存管理與智能指針的相關(guān)知識(shí)點(diǎn),需要的朋友可以參考下
    2022-03-03
  • 深入理解c++實(shí)現(xiàn)Qt信號(hào)和槽機(jī)制

    深入理解c++實(shí)現(xiàn)Qt信號(hào)和槽機(jī)制

    信號(hào)和槽機(jī)制是 Qt 的核心機(jī)制,可以讓編程人員將互不相關(guān)的對(duì)象綁定在一起,實(shí)現(xiàn)對(duì)象之間的通信,本文就來深入理解c++實(shí)現(xiàn)Qt信號(hào)和槽機(jī)制,感興趣的可以了解一下
    2023-08-08
  • C語言數(shù)據(jù)的存儲(chǔ)超詳細(xì)講解中篇練習(xí)

    C語言數(shù)據(jù)的存儲(chǔ)超詳細(xì)講解中篇練習(xí)

    使用編程語言進(jìn)行編程時(shí),需要用到各種變量來存儲(chǔ)各種信息。變量保留的是它所存儲(chǔ)的值的內(nèi)存位置。這意味著,當(dāng)您創(chuàng)建一個(gè)變量時(shí),就會(huì)在內(nèi)存中保留一些空間。您可能需要存儲(chǔ)各種數(shù)據(jù)類型的信息,操作系統(tǒng)會(huì)根據(jù)變量的數(shù)據(jù)類型,來分配內(nèi)存和決定在保留內(nèi)存中存儲(chǔ)什么
    2022-04-04

最新評(píng)論