天天看點

C++程式設計基礎(6)記憶體配置設定

1.知識點

三步走:申請,釋放,指針置空。

1.1malloc、free函數

在C語言中記憶體malloc函數申請動态空間,以下展示其基本用法:

1 int *p = NULL;
2 p = (int *)malloc(sizeof(int) * 10);//申請
3 free(p);//釋放,否則會造成記憶體洩漏
4 p = NULL;//指針置空,否則成為野指針      

(1)動态配置設定的空間來自隊空間,而指針本身作為局部變量存儲在棧空間中。

(2)malloc有時候也可能申請空間失敗,這時傳回NULL,故需要對其進行判斷。

(3)通過malloc動态申請的空間必須通過free函數釋放,這兩個函數成對出現。否則可用空間會越來越少。

(4)在通過free函數釋放之後,最好将指針置空。

(5)malloc/free函數申請釋放的過程其實就是可用空間連結清單不斷在更新。

1.2new、delete函數

(1)new和delete運算符既可以應用于基本類型,也可以用于自定義類型,new操作符不僅申請了空間,然後還根據提供的參數進行構造函數初始化,delete在釋放記憶體空間之前還會調用對象的析構函數,這些事new/delete比malloc/free更為豐富的地方。

2.面試題

2.1malloc和free的常識性問題

以下說法正确的是(D)。

(A)free會将指針置為空    //需要手動置空

(B)malloc函數的傳回指針移動後,free函數會自動找到首位址并釋放     //不能失去對首位址的控制,否則無法釋放

(C)malloc函數一次申請N個int空間,使用後需要循環N次逐一調用free釋放  //malloc和free成對出現

(D)malloc申請的空間位于堆上

2.2傳回一個64整數倍的位址

編寫兩個函數,align64malloc和align64free,分别用于申請空間和釋放空間,并要求申請空間傳回的位址必須是64的整數倍。

解析:在所需空間前面再加上64個位元組,可保證其中肯定有一個位址是64的倍數,再在這64個位元組空間的前面再加上4個位元組保證有地方可以存儲傳回的首位址。如下表所示

A 4個位元組
B 64個 位元組
C N個位元組
1 void * align64malloc(int size) {
 2     void *ptr = malloc(sizeof(int)*size + 64 + sizeof(void *));
 3     if (!ptr) {
 4         return NULL;
 5     }
 6     ptr = (char *)(ptr)+sizeof(void *);    //在最前面預留出來了存放首位址的存儲空間
 7     //接下來一步需要将首位址空間放入到64整數倍前面的空間中去
 8     *((int *)(((int)ptr+64-(int)ptr%64)-sizeof(void *)))=(int)ptr - sizeof(void *);//等式右邊為首位址,void*是不可以進行加減運算
 9     return  (void *)((int)ptr + 64 - (int)ptr % 64);
10 }
11 
12 void algin64free(void * ptr) {
13     if (ptr) {
14         free((void *)(*((void **)ptr - 1)));//void *不能進行加減,轉換成指針的指針之後可以進行加減
15     }
16 }      

2.3簡述malloc/free和new/delete的差別

(1)malloc/free是C語言提供的庫函數,通過函數調用通路,需要傳遞參數并接收傳回值;而new/delete是C++提供的操作符,有自己的一套文法規則和運算方式。

(2)malloc/free隻能用于基本的資料類型,而new/delete不但能用于基本資料類型,還可以用于面向對象中的自定義類型。

(3)malloc函數傳回的是void*類型,程式需要顯示的轉換成所需要的指針類型,new操作符後面直接指明了類型,不涉及類型轉換問題。

(4)malloc隻負責申請空間,并傳回首位址;new運算符除了申請空間,還會調用構造函數初始化指針指向的内容;free韓式隻負責 釋放空間,并辨別這段空間為可用空間;delete運算符除了釋放空間,還會調用對象的析構函數。

(5)事實上,後者覆寫了前者的全部功能,之是以在C++中還保留malloc/free函數,主要是為了解決相容性問題,防止C++中調用包含malloc/free的C函數時出現錯誤。

2.4簡述delete和delete[]的差別

答案(1)當new[]中數組的元素是基本類型時,通過delete和delete[]都可以釋放數組空間;

(2)當new[]中的數組元素是自定義的類型時,隻能通過delete[]釋放數組空間(因為用delete隻調用第一個元素的析構函數)。

強烈建議申請和釋放空間是采用完全配對的方式:new和delete成對使用,new[]和delete[]成對使用。

以下兩個例子說明:

1 //基本類型時二者都可以
2 //A
3 int *i = new int[5];
4 delete i;
5 //B
6 int *i = new int[5];
7 delete[] i;      
1 //自定義類型new[]/delete[]必須成對
 2 class Test {
 3 private:
 4     char *text;
 5 public:
 6     Test(int lenght = 100) {
 7         text = new char[lenght];
 8     }
 9     ~Test() {
10         delete text;
11         cout << "A destructor" << endl;
12     }
13 };
14 
15 Test *a = new Test[5];
16 delete[] a;//使用delete會出錯      

繼續閱讀