最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

詳解C++中動(dòng)態(tài)內(nèi)存管理和泛型編程

 更新時(shí)間:2022年10月19日 15:15:53   作者:蔣靈瑜的筆記本  
這篇文章主要為大家詳細(xì)介紹了C++中動(dòng)態(tài)內(nèi)存管理和泛型編程的相關(guān)資料,文中示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)C++具有一定幫助,感興趣的小伙伴快跟隨小編一起學(xué)習(xí)一

一、C/C++內(nèi)存區(qū)域劃分

1. 棧又叫堆棧--非靜態(tài)局部變量/函數(shù)參數(shù)/返回值等等,棧是向下增長(zhǎng)的。

2. 內(nèi)存映射段是高效的I/O映射方式,用于裝載一個(gè)共享的動(dòng)態(tài)內(nèi)存庫(kù)。用戶可使用系統(tǒng)接口創(chuàng)建共享共享內(nèi)存,做進(jìn)程間通信。

3. 堆用于程序運(yùn)行時(shí)動(dòng)態(tài)內(nèi)存分配,堆是可以上增長(zhǎng)的。

4. 數(shù)據(jù)段--存儲(chǔ)全局?jǐn)?shù)據(jù)和靜態(tài)數(shù)據(jù)。

5. 代碼段--可執(zhí)行的代碼/只讀常量。

二、常見(jiàn)變量存儲(chǔ)區(qū)域

int globalVar = 1;//全局變量中在靜態(tài)區(qū)
static int staticGlobalVar = 1;//靜態(tài)區(qū)
void Test()
{
    static int staticVar = 1;//靜態(tài)區(qū)
    int localVar = 1;//棧區(qū)
    int num1[10] = { 1, 2, 3, 4 };//棧區(qū)
    char char2[] = "abcd";//棧區(qū),*char2在棧區(qū)
    const char* pChar3 = "abcd";//指針在棧區(qū),*pchar3在常量區(qū)
    int* ptr1 = (int*)malloc(sizeof(int) * 4);//指針在棧區(qū),*ptr1在堆區(qū)
    int* ptr2 = (int*)calloc(4, sizeof(int));///棧區(qū)
    int* ptr3 = (int*)realloc(ptr2, sizeof(int) * 4);//棧區(qū)
    free(ptr1);
    free(ptr3);
}

三、new和delete

1、new和delete的使用方式

int main()
{
    int* p1 = new int;//在堆區(qū)申請(qǐng)一個(gè)int大小的空間,不會(huì)初始化
    int* p2 = new int(0);//申請(qǐng)并初始化為0
    delete p1;
    delete p2;
 
    int* p3 = new int[10];//在堆區(qū)申請(qǐng)一塊10個(gè)int大小的空間,未初始化
    int* p4 = new int[10]{ 1,2,3,4 };//初始化為{1,2,3,4,0,0,0,0,0,0}
    delete[] p3;
    delete[] p4;
    return 0;
}

注意:申請(qǐng)和釋放單個(gè)元素的空間,使用new和delete操作符,申請(qǐng)和釋放連續(xù)的空間,使用new[]和delete[],一定要匹配起來(lái)使用。

2、new、delete和malloc、free的區(qū)別

1、對(duì)于內(nèi)置類(lèi)型,沒(méi)有區(qū)別。

2、new和delete是C++的關(guān)鍵字/操作符,而malloc和free是C語(yǔ)言的庫(kù)函數(shù)。

3、對(duì)于自定義類(lèi)型,相比于malloc和free,new和delete會(huì)額外調(diào)用類(lèi)中的構(gòu)造函數(shù)和析構(gòu)函數(shù)。

4、malloc的返回值是void*,使用時(shí)需要強(qiáng)轉(zhuǎn),new后邊跟的是空間的類(lèi)型,所以new不需要強(qiáng)轉(zhuǎn)。

5、malloc失敗返回空指針,需要判空;new失敗拋異常,需要捕獲異常。

3、new的原理

new等于operator new()+構(gòu)造函數(shù)。operator new()不是new運(yùn)算符的重載,因?yàn)閰?shù)沒(méi)有自定義類(lèi)型。它是一個(gè)庫(kù)里的全局函數(shù)。

void *__CRTDECL operator new(size_t size) _THROW1(_STD bad_alloc) 
{
// try to allocate size bytes
    void *p;
    while ((p = malloc(size)) == 0)
         if (_callnewh(size) == 0)
         {
             // report no memory
             // 如果申請(qǐng)內(nèi)存失敗了,這里會(huì)拋出bad_alloc 類(lèi)型異常
             static const std::bad_alloc nomem;
             _RAISE(nomem);
         }
    return (p);
}

從底層代碼可以看出operator new()是對(duì)malloc的封裝,如果malloc失敗,將會(huì)拋出異常。

4、delete的原理

delete等于operator delete()+析構(gòu)函數(shù)

//operator delete: 該函數(shù)最終是通過(guò)free來(lái)釋放空間的
void operator delete(void *pUserData) {
     _CrtMemBlockHeader * pHead;
     RTCCALLBACK(_RTC_Free_hook, (pUserData, 0));
     if (pUserData == NULL)
         return;
     _mlock(_HEAP_LOCK);  /* block other threads */
     __TRY
         /* get a pointer to memory block header */
         pHead = pHdr(pUserData);
          /* verify block type */
         _ASSERTE(_BLOCK_TYPE_IS_VALID(pHead->nBlockUse));
         _free_dbg( pUserData, pHead->nBlockUse );//調(diào)用free()
     __FINALLY
         _munlock(_HEAP_LOCK);  /* release other threads */
     __END_TRY_FINALLY
     return; }
//free的實(shí)現(xiàn)
#define   free(p)               _free_dbg(p, _NORMAL_BLOCK)

從底層代碼可以看出operator delete()調(diào)用了free。

所以針對(duì)內(nèi)置類(lèi)型或無(wú)資源的類(lèi)對(duì)象delete時(shí),使用delete和free效果相同。但對(duì)于有資源需要釋放的對(duì)象時(shí),直接使用free雖然釋放了對(duì)象的空間,但對(duì)象內(nèi)部的資源還未被清理,導(dǎo)致內(nèi)存泄漏!這種情況必須使用delete。

5、new T[N]原理

1、new T[N]調(diào)用operator new[]

2、operator new[]調(diào)用operator new完成N個(gè)對(duì)象空間的開(kāi)辟。

3、調(diào)用N次構(gòu)造函數(shù)完成N個(gè)對(duì)象的初始化。

6、delete[]原理

1、調(diào)用N次析構(gòu)函數(shù)完成N個(gè)對(duì)象資源的清理工作。

2、調(diào)用operator delete[]

3、operator delete[]調(diào)用operator delete完成整段空間的釋放。

四、定位new

1、定位new的概念

對(duì)于一個(gè)類(lèi),我們可以顯式的去調(diào)用類(lèi)的析構(gòu)函數(shù),但是不能顯式調(diào)用構(gòu)造函數(shù),那么使用定位new,就可以顯式調(diào)用類(lèi)的構(gòu)造函數(shù),對(duì)一塊空間重新初始化。

2、定位new的使用格式

new (指針)類(lèi)名或者new (指針) type(初始化列表)

int main()
{
    Date d1;
    new(&d1)Date;//new (指針)類(lèi)名
    Date* p = new Date[4]{ {2022,10,15},{2023,11,8} };
    new(p)Date[4];//new (指針) type(初始化列表)
    delete[] p;
    return 0;
}

上述代碼一共調(diào)用了10次構(gòu)造函數(shù),經(jīng)過(guò)定位new的處理,d1和p所代表的空間已經(jīng)被重新初始化了。

3、定位new的使用場(chǎng)景

一般不會(huì)像上邊代碼一樣,對(duì)一塊已有對(duì)象數(shù)據(jù)的空間重新初始化。定位new表達(dá)式在實(shí)際中一般是配合內(nèi)存池使用。因?yàn)閮?nèi)存池分配出的內(nèi)存沒(méi)有初始化,對(duì)于自定義類(lèi)型的對(duì)象,可以使用定位new對(duì)這些沒(méi)有被初始化的內(nèi)存顯式調(diào)用類(lèi)的構(gòu)造函數(shù)初始化。

五、泛型編程

泛型編程:編寫(xiě)與類(lèi)型無(wú)關(guān)的通用代碼,是代碼復(fù)用的一種手段。模板是泛型編程的基礎(chǔ)。

模板分為函數(shù)模板和類(lèi)模板

六、函數(shù)模板

1、函數(shù)模板的使用

template<typename T>
void Swap(T& a, T& b)
{
    T tmp = a;
    a = b;
    b = tmp;
}
int main()
{
    int a = 10, b = 5;
    double m = 2.3, n = 4.9;
    Swap(a, b);
    Swap(m, n);
    return 0;
}

兩個(gè)Swap調(diào)用的不是模板,而是模板生成的實(shí)例化函數(shù),像上述代碼中,模板會(huì)生成int和double類(lèi)型的兩種實(shí)例化函數(shù)。

2、不同類(lèi)型形參傳參時(shí)的處理

2.1傳參時(shí)強(qiáng)轉(zhuǎn)(對(duì)應(yīng)形參需要const修飾)

template<typename T>
T Add(const T& a,const T& b)//const接收常性實(shí)參
{
    return a + b;
}
int main()
{
    int a = 10, b = 5;
    double m = 2.3, n = 4.9;
    Add(a, (int)m);//強(qiáng)轉(zhuǎn),臨時(shí)變量傳參,具有常性
    return 0;
}

使用強(qiáng)制類(lèi)型轉(zhuǎn)換在推演的時(shí)候?qū)⑿螀⑥D(zhuǎn)換成同一類(lèi)型。

2.2顯式實(shí)例化(傳參時(shí)隱式類(lèi)型轉(zhuǎn),對(duì)應(yīng)形參需要const修飾)

template<typename T>
T Add(const T& a, const T& b)//需要使用const接收
{
    return a + b;
}
int main()
{
    int a = 10, b = 5;
    double m = 2.3, n = 4.9;
    Add<int>(a, m);//顯式實(shí)例化,m發(fā)生隱式類(lèi)型轉(zhuǎn)換
    return 0;
}

顯式實(shí)例化編譯器不再去推演T的類(lèi)型,而是直接使用尖括號(hào)內(nèi)的類(lèi)型實(shí)例化對(duì)應(yīng)函數(shù)。

2.3使用多個(gè)模板

template<typename T1,class T2>//可以寫(xiě)typename也可以寫(xiě)class
T1 Add(const T1& a, const T2& b)
{
    return a + b;
}
int main()
{
    int a = 10, b = 5;
    double m = 2.3, n = 4.9;
    Add(a, m);//Add<int,double>(a,m);多個(gè)模板的手動(dòng)推演
    return 0;
}

3、模板和實(shí)例可以同時(shí)存在,編譯器會(huì)優(yōu)先調(diào)用實(shí)例 

template<typename T>//可以寫(xiě)typename也可以寫(xiě)class
T Add(const T& a, const T& b)
{
    return a + b;
}
int Add(const int& a, const int& b)
{
    return a + b;
}
int main()
{
    int a = 10, b = 5;
    double m = 2.3, n = 4.9;
    Add(a, m);//調(diào)用已有實(shí)例
    Add<int>(a, m);//調(diào)用模板生成的實(shí)例
    return 0;
}

1、模板和普通函數(shù)的函數(shù)名修飾規(guī)則是不一樣的。

2、模板和實(shí)例可以同時(shí)存在,編譯器會(huì)優(yōu)先調(diào)用實(shí)例。如果想使用模板生成的實(shí)例,必須使用尖括號(hào)指定類(lèi)型。

3、如果模板可以生成更加匹配的版本,編譯器將會(huì)生成這個(gè)匹配版本而不是使用那個(gè)已有但不太匹配的實(shí)例。

六、類(lèi)模板

1、對(duì)象定義時(shí)需要顯式實(shí)例化

int main()
{
    Stack<double> st1; // double
    st1.Push(1.1);
    Stack<int> st2; // int
    st2.Push(1);
    return 0;
}

函數(shù)模板可以通過(guò)傳參確定T的類(lèi)型,但是類(lèi)模板編譯器無(wú)法推演,必須要在對(duì)象定義時(shí)顯式實(shí)例化類(lèi)型。

模板參數(shù)不同,他們就是不同的類(lèi)型。st1和st2屬于不同的類(lèi)定義出的兩個(gè)對(duì)象。所以不能有st1=st2,因?yàn)樗麄儾皇峭粋€(gè)類(lèi),除非針對(duì)這種賦值,自己寫(xiě)一個(gè)賦值重載。

2、為什么stl被稱(chēng)為模板

類(lèi)模板和函數(shù)模板不同,需要在實(shí)例化的時(shí)候在類(lèi)名后加上<類(lèi)型>。

類(lèi)模板不是真正的類(lèi),而實(shí)例化出來(lái)的才是真正的類(lèi)。

// Vector是類(lèi)模板,Vector<int>才是類(lèi)型
Vector<int> s1;
Vector<double> s2;

以上就是詳解C++中動(dòng)態(tài)內(nèi)存管理和泛型編程的詳細(xì)內(nèi)容,更多關(guān)于C++動(dòng)態(tài)內(nèi)存管理 泛型編程的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • C++單例模式為何要實(shí)例化一個(gè)對(duì)象不全部使用static

    C++單例模式為何要實(shí)例化一個(gè)對(duì)象不全部使用static

    這篇文章主要介紹了C++單例模式為何要實(shí)例化一個(gè)對(duì)象不全部使用static,文基于C++圍繞主題展開(kāi)詳細(xì)內(nèi)容,需要的小伙伴可以參考一下
    2022-05-05
  • C++ 虛函數(shù)和純虛函數(shù)的區(qū)別分析

    C++ 虛函數(shù)和純虛函數(shù)的區(qū)別分析

    這篇文章主要介紹了C++ 虛函數(shù)和純虛函數(shù)的區(qū)別,幫助大家更好的理解和學(xué)習(xí)c++的相關(guān)知識(shí),感興趣的朋友可以了解下
    2020-10-10
  • C++實(shí)現(xiàn)圖片轉(zhuǎn)base64的示例代碼

    C++實(shí)現(xiàn)圖片轉(zhuǎn)base64的示例代碼

    Base64就是一種 基于64個(gè)可打印字符來(lái)表示二進(jìn)制數(shù)據(jù)的表示方法,本文主要為大家詳細(xì)介紹了如何使用C++實(shí)現(xiàn)圖片轉(zhuǎn)base64,需要的可以參考下
    2024-04-04
  • C++核心編程之內(nèi)存分區(qū)詳解

    C++核心編程之內(nèi)存分區(qū)詳解

    這篇文章主要為大家詳細(xì)介紹了C++核心編程之內(nèi)存分區(qū),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助
    2022-03-03
  • C++?STL反向迭代器的實(shí)現(xiàn)

    C++?STL反向迭代器的實(shí)現(xiàn)

    本文主要介紹了C++?STL反向迭代器的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-07-07
  • Lambda表達(dá)式里面修改外部變量問(wèn)題

    Lambda表達(dá)式里面修改外部變量問(wèn)題

    這篇文章主要介紹了Lambda表達(dá)式里面修改外部變量的相關(guān)知識(shí),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-03-03
  • C++11原子操作詳解

    C++11原子操作詳解

    這篇文章主要為大家介紹了C++的原子操作,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助
    2021-11-11
  • C語(yǔ)言結(jié)構(gòu)體的一些理解

    C語(yǔ)言結(jié)構(gòu)體的一些理解

    這篇文章主要給大家介紹了關(guān)于C語(yǔ)言結(jié)構(gòu)體的一些理解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-11-11
  • C++使用jsoncpp庫(kù)解析Json

    C++使用jsoncpp庫(kù)解析Json

    對(duì)json的解析操作是我們?nèi)粘i_(kāi)發(fā)中經(jīng)常會(huì)遇到的一個(gè)需求,下面這篇文章主要給大家介紹了關(guān)于C++使用jsoncpp庫(kù)解析Json的相關(guān)資料,需要的朋友可以參考下
    2021-06-06
  • C語(yǔ)言數(shù)據(jù)結(jié)構(gòu)之簡(jiǎn)易計(jì)算器

    C語(yǔ)言數(shù)據(jù)結(jié)構(gòu)之簡(jiǎn)易計(jì)算器

    這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言數(shù)據(jù)結(jié)構(gòu)之簡(jiǎn)易計(jì)算器,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-11-11

最新評(píng)論

嘉峪关市| 大埔区| 张家港市| 全南县| 布尔津县| 西峡县| 鸡泽县| 红河县| 新闻| 兴隆县| 白城市| 海晏县| 汝阳县| 乐昌市| 浦江县| 溧阳市| 白城市| 澜沧| 巴楚县| 上林县| 福泉市| 通城县| 惠安县| 石台县| 双城市| 册亨县| 通渭县| 邻水| 商丘市| 马尔康县| 周至县| 南涧| 曲周县| 六盘水市| 新巴尔虎左旗| 门头沟区| 涟源市| 洛阳市| 邮箱| 荆州市| 临泉县|