您好,登錄后才能下訂單哦!
這篇文章主要介紹C++ 使用new與delete需注意的事項有哪些,文中介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們一定要看完!
C++的動態內存管理是通過new和delete兩個操作來完成的,即用new來申請空間,用delete來釋放空間。在使用new和delete時,注意以下原則。
1.new與delete需一一對應
用new操作申請空間,如果申請成功,必須在以后的某個時刻用delete釋放該空間,既不能忘記釋放,也不能多次釋放。前者會引起內存泄露,后者會引起運行時錯誤。如下面的程序。
#include <iostream> using namespace std; int main() { int *p; p=new int(3); if(p) { delete p; } delete p; return 0; }
以上程序對指針p所指向的空間進行兩次釋放,這種內存錯誤對C++程序危害極大,也是很多人對C++忘而卻步的原因。多次釋放同一塊內存空間,并不一定立即引起程序運行錯誤,也不一定會導致程序運行的崩潰,這跟具體的編譯器實現有關。但是,多次釋放同一塊內存空間絕對是一個編程錯誤,這個編程錯誤可能會在其后的某個時刻導致其他的邏輯錯誤的發生,從而給程序的調試和糾錯帶來困難。考察如下程序。
#include <iostream> using namespace std; int main() { int *p,*q,*one; one=new int; if(one) { cout<<one<<endl; } delete one; p=new int(3); if(p) { cout<<p<<endl; } delete one;//假設這句語句是程序員不小心加上的 q=new int(5); if(q) { cout<<q<<endl; } cout<<(*p)+(*q)<<endl; delete p; delete q; }
程序通過編譯,運行結果如下:
003289A0
003289A0
003289A0
10
程序運行過程中會產生中斷。從程序的輸出可以看出,在將指針one所指向的空間釋放后,為指針p申請的空間就是原來one所指向的空間。由于不小心在為p分配空間之后再次使用了delete one,導致q申請到的空間就是原來p所申請的空間,這樣賦給*q的值就改寫了原來p所指向的單元的值,導致最后輸出結果為10。由此可知,多次釋放同一塊內存空間,即使不導致程序運行中斷,也會破壞環境,使指針與所對應的空間的隸屬關系出現混亂,從而導致邏輯錯誤。在大型程序設計中,這種邏輯錯誤的查找會變得十分費時費力。
**注意:**當指針p的值為NULL時,多次使用delete p并不會帶來麻煩,因為釋放空指針的空間實際上不會導致任何操作。所以,將“不用”的指針設置為NULL是一個好的編程習慣。
2.new[]與delete[]需一一對應
在申請對象數組時,需要使用new[]運算符,與之對應,釋放對象數組時,需要使用delete[]運算符。這一點與C語言有所區別,C中無論申請單個還是多個對象,均使用malloc()/free()函數。首先看一下delete與delete[]運算符的區別。
class Test { public: Test() { cout<<"ctor"<<endl; } ~Test() { cout << "dtor" << endl; } }; //segment1 Test* pArray1 = new Test[3]; delete pArray1; //segment2 Test* pArray2 = new Test[3]; delete[] pArray2;
其中代碼片段segment1運行結果如下:
ctor
ctor
ctor
dtor
segment2運行結果如下:
ctor
ctor
ctor
dtor
dtor
dtor
可以看出,delete與delete[]區別在于釋放對象數組時,delete只調用了一次析構函數,delete[]調用了三次析構函數,完成了對象數組的釋放。實際上,在使用new和new[]申請內存空間時,會申請一段額外的內存來保存用戶申請的內存空間大小,元素個數等信息。當使用delete[]釋放內存空間時,會逐個調用對象的析構函數并完成最終的內存空間的釋放。使用delete釋放對象數組時,則只會調用單個對象的析構函數,造成內存泄漏。符號[]告訴編譯器,在delete一塊內存時,先去獲取內存保存的元素個數,然后一一清理。所以使用delete釋放new[]申請的內存空間和使用delete[]釋放new申請的內存空間都錯誤的做法。
具體使用時,需要注意以下兩點:
(1)對于內置數據類型,因為沒有構造和析構函數,所以使用delete和delete[]的效果是一樣的。比如:
int* pDArr=new int[3]; //processing code delete pDArr; //等同于delete[] pDArr
對于內置數據類型,雖然可以使用delete完成對象數組內存空間的釋放,但是為了保證代碼的可讀性,建議使用delete[]來完成。所以,new[]與delete[]使用時應一一對應。
(2)對于經常使用typedef的程序員來說,很容易new[]與delete的混用,例如有如下操作:
typedef int Height[NUM]; int* pHeight=new Height;
這個情況應該使用delete還是delete[]呢?答案如下:
delete pHeight; //wrong,但容易錯誤地使用delete delete[] pHeight; //right
為了避免出現上面的錯誤,建議不要對數組使用typedef,或者采用STL中的vector代替數組。
3.構造函數中的new/new[]與析構函數的中delete/delete[]需一一對應
當類的成員中有指針變量時,在構造函數中用new申請空間并且在析構函數中用delete釋放空間是一種“標準的”、安全的做法。例如下面的程序。
#include <iostream> using namespace std; class Student { char* name; public: Student() { cout<<"Default constructor"<<endl; } Student(char*); ~Student(); }; Student::Student(char*s) { //Student();//此句運行時報錯,構造函數不能調用其他構造函數 cout<<"In constructor,allocating space"<<endl; name=new char[strlen(s)+1]; strcpy(name,s); cout<<"name:"<<name<<endl; } Student::~Student() { cout<<"In destructor, free space"<<endl; delete name; } int main() { Student s1("張三"); }
程序運行輸出:
In constructor,allocating space
name:張三
In destructor, free space
由于任何一個對象,其構造函數只調用一次,其析構函數也只調用一次,這樣就能保證運行時new和delete操作是一一對應的,也就保證了內存管理的安全性。
在C++中,一個構造函數不能調用本類的另一個構造函數,其原因就是為了防止構造函數的相互調用打破了內存申請與釋放之間的這種對應關系。
以上是C++ 使用new與delete需注意的事項有哪些的所有內容,感謝各位的閱讀!希望分享的內容對大家有幫助,更多相關知識,歡迎關注億速云行業資訊頻道!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。