1.C++中delete之後指針指向問題
在C++中經常需要用new進行動態內存分配,然後使用delete或者delete[]進行內存的釋放。但是實際上delete並沒有刪除指針本身,而是標記指針指向的那塊內存區域可用,如果不講指針置爲空的話,便會造成一定的風險。例如:delete ptr;執行之後,ptr指針仍然存在,並且會隨機指向一個地址,如果後續程序仍然需要訪問ptr這個指針就會造成風險。
通過下面簡單的例子就可以看出來:
#include<iostream>
using namespace std;
void main()
{
int *ptr = new int;//爲ptr分配1個int的內存
*ptr = 5;
cout << "刪除指針前指針地址:" << ptr<<endl;
delete ptr;//刪除指針
cout << "刪除指針後指針地址:" << ptr << endl;
}
上面這個小例子足以說明這個問題,因此在書寫程序的時候應當注意將指針指向nullptr。
- C++中delete與delete[]的區別以及濫用造成的問題
C++中提供delete和delete[]兩種方式對內存進行釋放,但他們只能釋放new動態分配的內存。這兩種方式分別適用於不同的情況,delete是對指向單個元素或者對象的指針進行釋放,如上1中所示。而delete[]是對數組或者對象數組進行內存的釋放,例如:
Int *ptr=new int[4];//分配4個int型內存空間
delete[] ptr;//釋放該空間
對於普通數組型的內存釋放,使用delete和delete[]他們沒有多大區別,因爲它們直接將分配的內存塊標記成可用。但是對於對象數組錯誤的使用delete和delete[]便會出現一些問題。
第一種情況:對單個對象使用delete進行內存釋放
例如:
#include<iostream>
using namespace std;
class Test{
public:
~Test() { cout << "調用析構函數" << endl; }
};
void main()
{
Test *ptr=new Test;//分配一個對象長度的內存
delete[] ptr;//用delete[]釋放該內存
}
在上面的簡短例子中,建立了一個Test類用於測試,其中僅僅有一個析構函數。然後用new分配了一個Test類對象的空間,再用delete[]對內存進行釋放,此時會出現無限次調用析構函數的情況。造成這個問題的原因是什麼呢?首先我們從使用new對對象數組進行內存分配方式說起。
例如:Test *ptr=new Test[10];//使用new分配10個Test對象長度的內存
實際上執行的時候是new[](10*sizeof(Test)+4),即分配了(10*sizeof(Test)+4)長度的內存空間,多處的4個字節用於存儲10這個數字,在對對象數組進行析構的時候便知道調用析構函數的次數。而當使用delete[]對單個對象進行釋放時,編譯器認爲刪除的時一個對象數組,便會訪問Test分配內存空間的後面4個字節,來知道進行析構的次數。然而後面四個字節並不是一個賦予了的值而是一個隨機值,所以就出現了無限析構的錯誤。那麼具體析構多少次呢?這就要由那四個字節中的垃圾數據來決定了。
第二中種情況:使用delete對對象數組進行釋放
#include<iostream>
using namespace std;
class Test{
public:
~Test() { cout << "調用析構函數" << endl; }
};
void main()
{
Test *ptr=new Test[4];//分配4個對象長度的內存
delete ptr;//用delete釋放該內存
}
在上例中用new分配了四個Test對象長度的對象數組,然後使用delete對指針ptr進行釋放。最後的運行結果如圖所示,本來四個對象應當進行四次析構,但是實際上只執行了一次析構。這是因爲使用delete時,編譯器默認其爲單個對象,因此便只調用了一次析構函數,這樣就造成了剩下的對象空間並未釋放,造成了隱患。
- 總結
這是在學習C++中遇到的比較困惑的一個問題,這裏寫一個小的總結,使自己印象更深刻。不能夠錯誤的使用delete和delete[],並且在使用之後記得對指針進行置空處理。