1. 程式人生 > >【C/C++開發】C++ 解構函式以及 delete 和delete[]的整理

【C/C++開發】C++ 解構函式以及 delete 和delete[]的整理

轉自:http://hi.baidu.com/bystander1983/item/bf0b5c12b077cfec9913d651

delete和delete[] 的區別:

C++告訴我們在回收用 new 分配的單個物件的記憶體空間的時候用 delete,回收用 new[] 分配的一組物件的記憶體空間的時候用 delete[]。

很多人注意到了這個問題,但是卻不清楚為什麼要這樣做,不這樣做行不行。

關於 new[] 和 delete[],其中又分為兩種情況:(1) 為基本資料型別分配和回收空間;(2) 為自定義型別分配和回收空間。

對於 (1),毫無疑問 delete[] 和 delete 是等同的。但是對於 (2),情況就發生了變化。

delete p1 在回收空間的過程中,只有 p1[0] 這個物件呼叫了解構函式,其它物件如 p1[1]、p1 [2] 等都沒有呼叫自身的解構函式,這就是問題的癥結所在。如果用 delete[],則在回收空間之前所有物件都會首先呼叫自己的解構函式。

基本型別的物件沒有解構函式,所以回收基本型別組成的陣列空間用 delete 和 delete[] 都是應該可以的;但是對於類物件陣列,只能用 delete[]。對於 new 的單個物件,只能用 delete 不能用 delete[] 回收空間。

所以一個簡單的使用就是:new 和 delete、new[] 和 delete[] 對應使用。

轉自:http://www.diybl.com/course/3_program/c++/cppsl/2008927/146231.html

現將《Effective C++》中正確的觀點、結論摘錄如下:
  1. 當你使用new時,有兩件事會發生。第一,記憶體被配置(透過函式operator new)。第二,會有一個(或以上)的constructors針對此記憶體被呼叫。當你使用delete時,也有兩件事發生:一個(或以上)的destructors會針對此記憶體被呼叫,然後記憶體被釋放(透過函式operator delete)。
  2. 如果你使用delete是未加括號,delete便假設刪除物件是單一物件。否則便假設刪除物件是個陣列。
  3. string *stringPtr1 = new string;
  string *stringPtr2 = new string[100];
  ……
  delete stringPtr1;
  delete [] stringPtr2;
  如果你對著stringPtr1使用“[]”形式,其結果未定義。如果你對著stringPtr2沒有使用“[]”形式,其結果亦未定義。猶有進者,這對內建型別如int者亦未定義,即使這類型別並沒有destructors。
  4. 因此,遊戲規則很簡單,如果你在呼叫new時使用了[],則你在呼叫delete時也使用[],如果你在呼叫new的時候沒有[],那麼你也不應該在呼叫時使用[]。


解構函式的作用:
轉自:http://see.xidian.edu.cn/cpp/biancheng/view/196.html 解構函式(destructor)也是一個特殊的成員函式,它的作用與建構函式相反,它的名字是類名的前面加一個“~”符號。

在C++中“~”是位取反運算子,從這點也可以想到:解構函式是與建構函式作用相反的函式。當物件的生命期結束時,會自動執行解構函式。

具體地說如果出現以下幾種情況,程式就會執行解構函式:
①如果在一個函式中定義了一個物件(它是自動區域性物件),當這個函式被呼叫結束時,物件應該釋放,在物件釋放前自動執行解構函式。
②static區域性物件在函式呼叫結束時物件並不釋放,因此也不呼叫解構函式,只在main函式結束或呼叫exit函式結束程式時,才呼叫static區域性物件的解構函式。
③如果定義了一個全域性物件,則在程式的流程離開其作用域時(如main函式結束或呼叫exit函式) 時,呼叫該全域性物件的解構函式。
④如果用new運算子動態地建立了一個物件,當用delete運算子釋放該物件時,先呼叫該物件的解構函式。

解構函式的作用並不是刪除物件,而是在撤銷物件佔用的記憶體之前完成一些清理工作,使這部分記憶體可以被程式分配給新物件使用。程式設計者事先設計好解構函式,以完成所需的功能,只要物件的生命期結束,程式就自動執行解構函式來完成這些工作。

注意:解構函式不返回任何值,沒有函式型別,也沒有函式引數。因此它不能被過載。一個類可以有多個建構函式,但只能有一個解構函式。

實際上,解構函式的作用並不僅限於釋放資源方面,它還可以被用來執行“使用者希望在最後一次使用物件之後所執行的任何操作”,例如輸出有關的資訊。這裡說的使用者是指類的設計者,因為,解構函式是在宣告類的時候定義的。也就是說,解構函式可以完成類的設計者所指定的任何操作。

一般情況下,類的設計者應當在宣告類的同時定義解構函式,以指定如何完成“清理”的工作。如果使用者沒有定義解構函式,C++編譯系統會自動生成一個解構函式,但它只是徒有解構函式的名稱和形式,實際上什麼操作都不進行。想讓解構函式完成任何工作,都必須在定義的解構函式中指定。