1. 程式人生 > >c/c++ 動態記憶體管理(一)

c/c++ 動態記憶體管理(一)

C語言中

使用:malloc/calloc/realloc/free 進行動態記憶體管理
calloc:分配n個長度為size的連續記憶體空間,並初始為0
realloc:重新分配空間
void* realloc(void* p,size_t size)
p為指向之前分配的記憶體塊的指標

int*p1=(int*)malloc(sizeof(int)*4);
int*p2=(int*)calloc(4,sizeof(int));
int*p3=(int*)realloc(p2,sizeof(int)*6);

free(p1);
//p2不需要釋放,否則會重複釋放
free(p3);

注意點:

這裡寫圖片描述

C++中

使用:new/delete
new[ ]/delete[ ] 進行動態記憶體管理

int* p4=new int;//動態分配4個位元組(int)
int* p5=new int(2);//動態分配4個位元組,並初始化為2
int* p6=new int[2];//動態分配8個位元組(2*4),2為物件個數

delete p4;
delete p5;
delete p6[];

深入理解動態記憶體管理

一、malloc/free和new/delete的區別和聯絡

  1. 都是用來動態管理記憶體的
  2. malloc/free是c語言中的;new/delete是c++中的
  3. malloc/free只分配/釋放空間;
    new/delete因為是在c++中才有的(c++中有類的概念),所以除了分配空間還會呼叫建構函式和解構函式進行初始化與清理
  4. new/deiete會自己計算型別的大小,返回對應型別的指標

探究new/delete

這裡要提到operator new和operator delete函式,這是兩個標準庫函式。這兩個函式沒有過載new和delete。
這裡寫圖片描述
按F11除錯,我們會發現new其實呼叫了operator new函式

operator new與new

operator new與malloc用法一樣
operator new只負責分配空間,不會呼叫物件的建構函式,
實際上operator new/operator delete只是malloc/free的一層封裝

總結:

new做了兩件事

  1. 呼叫operator new分配空間
  2. 呼叫建構函式初始化物件

new[N]

  1. 呼叫operator new分配空間
  2. 呼叫N次建構函式分別初始化每個物件

delete同理

定位new表示式

new的定位表示式是在已分配的原始記憶體空間中呼叫建構函式構造物件
優點:建立物件但是不分配記憶體,而是在已有的記憶體塊上面建立物件。用於需要反覆建立並刪除的物件,可以降低分配釋放記憶體的效能消耗。  就是一次把記憶體給夠,不要老是向作業系統要記憶體

new (place_address) type
new (place_address) type(initializer-list)
place_address必須是一個指標,initializer-list是型別的初始化列表。

1.malloc/free + 定位操作符new()/顯示呼叫解構函式,模擬 new和delete 的行為
2.malloc/free + 多次呼叫定位操作符new()/顯示呼叫解構函式,模擬 new[]和delete[] 的行為

使用起來,簡單來說就四部

AA*p1=(AA*)operator new(sizeof(AA));//開空間
new(p1)AA;//構造物件
p1->~AA();//銷燬物件
operator delete(p1);釋放掉空間,還回系統

如何使用?

class AA
{
public:
    AA(int a = 0,int b=0)
        :_a(a)
        ,_b(b)
    {}

    void Show()
    {
        cout <<_a<<"->"<<_b<<endl;
    }

    ~AA() 
    {
        cout << "~AA()"<< endl;
    }

private:
    int _a;
    int _b;
};

int main()
{
    //1、開闢空間,一個大的記憶體池,將空間一次給夠
    //兩種開闢方式:
    AA* p = (AA*)malloc(sizeof(AA)* 3);
    //AA* p=(AA*)operator new(sizeof(AA)*3);

    //用剛才開闢的空間
    AA* pb1 = new (p)AA(0,1);
    pb1->Show(); //0->1
    pb1->~AA();//調析構,銷燬物件,但不會釋放記憶體


    AA* pb2 = new (p+1)AA(1,2);
    pb2->Show();  //1->2
    pb2->~AA();

    AA* pb3 = new (p+ 2)AA(2,3);
    pb3->Show();  //2->3
    pb3->~AA();

    free(p);
    //operator delete(p);//使用完空間成後手動釋放空間

    system("pause");
    return 0;
}

這裡寫圖片描述