最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

全面解析C++中的析構函數

 更新時間:2016年01月22日 14:25:47   投稿:goldensun  
這篇文章主要介紹了C++中的析構函數,為C++入門學習中的基礎知識,需要的朋友可以參考下

“析構函數”是構造函數的反向函數。在銷毀(釋放)對象時將調用它們。通過在類名前面放置一個波形符 (~) 將函數指定為類的析構函數。例如,聲明 String 類的析構函數:~String()。
在 /clr 編譯中,析構函數在釋放托管和非托管資源方面發(fā)揮了特殊作用。
析構函數通常用于在不再需要某個對象時“清理”此對象。請考慮 String 類的以下聲明:

// spec1_destructors.cpp
#include <string.h>

class String {
public:
  String( char *ch ); // Declare constructor
  ~String();      // and destructor.
private:
  char  *_text;
  size_t sizeOfText;
};

// Define the constructor.
String::String( char *ch ) {
  sizeOfText = strlen( ch ) + 1;

  // Dynamically allocate the correct amount of memory.
  _text = new char[ sizeOfText ];

  // If the allocation succeeds, copy the initialization string.
  if( _text )
   strcpy_s( _text, sizeOfText, ch );
}

// Define the destructor.
String::~String() {
  // Deallocate the memory that was previously reserved
  // for this string.
  if (_text)
   delete[] _text;
}

int main() {
  String str("The piper in the glen...");
}

在前面的示例中,析構函數 String::~String 使用 delete 運算符來動態(tài)釋放為文本存儲分配的空間。
聲明析構函數
析構函數是具有與類相同的名稱但前面是波形符 (~) 的函數
該語法的第一種形式用于在類聲明中聲明或定義的析構函數;第二種形式用于在類聲明的外部定義的析構函數。
多個規(guī)則管理析構函數的聲明。析構函數:

  • 不接受參數。
  • 無法指定任何返回類型(包括 void)。
  • 無法使用 return 語句返回值。
  • 無法聲明為 const、volatile 或 static。但是,可以為聲明為 const、volatile 或 static 的對象的析構調用它們。
  • 可以聲明為 virtual。通過使用虛擬析構函數,無需知道對象的類型即可銷毀對象 - 使用虛函數機制調用該對象的正確析構函數。請注意,析構函數也可以聲明為抽象類的純虛函數。

使用構造函數

當下列事件之一發(fā)生時,將調用析構函數:
使用 delete 運算符顯式解除分配了使用 new 運算符分配的對象。使用 delete 運算符解除分配對象時,將為“大多數派生對象”或為屬于完整對象,但不是表示基類的子對象的對象釋放內存。此“大多數派生對象”解除分配一定僅對虛擬析構函數有效。在類型信息與實際對象的基礎類型不匹配的多重繼承情況下,取消分配可能失敗。
具有塊范圍的本地(自動)對象超出范圍。
臨時對象的生存期結束。
程序結束,并且存在全局或靜態(tài)對象。
使用析構函數的完全限定名顯式調用了析構函數。(有關詳細信息,請參閱顯式析構函數調用。)
前面的列表中所述的情況將確保所有對象均可通過用戶定義的方法進行銷毀。
如果基類或數據成員有一個可訪問的析構函數,并且派生類未聲明析構函數,則編譯器將生成一個析構函數。此編譯器生成的析構函數將為派生類型的成員調用基類析構函數和析構函數。默認析構函數是公共的。

析構函數可以隨意調用類成員函數和訪問類成員數據。從析構函數調用虛函數時,調用的函數是當前正在銷毀的類的函數。
析構的順序
當對象超出范圍或被刪除時,其完整析構中的事件序列如下所示:
將調用該類的析構函數,并且會執(zhí)行該析構函數的主體。
按照非靜態(tài)成員對象的析構函數在類聲明中的顯示順序的相反順序調用這些函數。用于這些成員的構造的可選成員優(yōu)化列表不影響構造或析構的順序。
非虛擬基類的析構函數以聲明的相反順序被調用。
虛擬基類的析構函數以聲明的相反順序被調用。

// order_of_destruction.cpp
#include <stdio.h>

struct A1   { virtual ~A1() { printf("A1 dtor\n"); } };
struct A2 : A1 { virtual ~A2() { printf("A2 dtor\n"); } };
struct A3 : A2 { virtual ~A3() { printf("A3 dtor\n"); } };

struct B1   { ~B1() { printf("B1 dtor\n"); } };
struct B2 : B1 { ~B2() { printf("B2 dtor\n"); } };
struct B3 : B2 { ~B3() { printf("B3 dtor\n"); } };

int main() {
  A1 * a = new A3;
  delete a;
  printf("\n");

  B1 * b = new B3;
  delete b;
  printf("\n");

  B3 * b2 = new B3;
  delete b2;
}

輸出:

A3 dtor
A2 dtor
A1 dtor

B1 dtor

B3 dtor
B2 dtor
B1 dtor

虛擬基類
按照與虛擬基類在定向非循環(huán)圖形中顯示的順序的相反順序調用這些虛擬基類的析構函數(深度優(yōu)先、從左到右、后序遍歷)。下圖描述了繼承關系圖。

2016122142248275.jpeg (107×121)

演示虛擬基類的繼承關系圖
下面列出了圖中顯示的類的類頭。

  • class A
  • class B
  • class C : virtual public A, virtual public B
  • class D : virtual public A, virtual public B
  • class E : public C, public D, virtual public B

為了確定 E 類型的對象的虛擬基類的析構順序,編譯器將通過應用以下算法來生成列表:

  1. 向左遍歷關系圖,并從關系圖中的最深點開始(在此示例中,為 E)。
  2. 執(zhí)行左移遍歷,直到訪問了所有節(jié)點。記下當前節(jié)點的名稱。
  3. 重新訪問上一個節(jié)點(向下并向右)以查明要記住的節(jié)點是否為虛擬基類。
  4. 如果記住的節(jié)點是虛擬基類,請瀏覽列表以查看是否已將其輸入。如果它不是虛擬基類,則將其忽略。
  5. 如果記住的節(jié)點尚未包含在列表中,請將其添加到列表的底部。
  6. 向上遍歷關系圖并沿下一個路徑向右遍歷。
  7. 轉到步驟 2。
  8. 在用完最后一個向上路徑時,請記下當前節(jié)點的名稱。
  9. 轉到步驟 3。
  10. 繼續(xù)執(zhí)行此過程,直到底部節(jié)點再次成為當前節(jié)點。

因此,對于 E 類,析構順序為:

  1. 非虛擬基類 E。
  2. 非虛擬基類 D。
  3. 非虛擬基類 C。
  4. 虛擬基類 B。
  5. 虛擬基類 A。

此過程將生成唯一項的有序列表。任何類名均不會出現(xiàn)兩次。在構造列表后,將以相反的順序遍歷該列表,并且將調用列表中每個類(從最后一個到第一個)的析構函數。

如果某個類中的構造函數或析構函數依賴于要先創(chuàng)建或保留更長時間的另一個組件(例如,如果 A 的析構函數(上圖中所示)依賴于執(zhí)行其代碼時仍存在 B),則構造或析構的順序特別重要,反之亦然。
繼承關系圖中各個類之間的這種相互依賴項本質上是危險的,因為稍后派生類可以更改最左邊的路徑,從而更改構造和析構的順序。
非虛擬基類
按照相反的順序(按此順序聲明基類名稱)調用非虛擬基類的析構函數??紤]下列類聲明:

class MultInherit : public Base1, public Base2
...

在前面的示例中,先于 Base2 的析構函數調用 Base1 的析構函數。
顯式析構函數調用
很少需要顯式調用析構函數。但是,對置于絕對地址的對象進行清理會很有用。這些對象通常使用采用位置參數的用戶定義的 new 運算符進行分配。 delete 運算符不能釋放該內存,因為它不是從自由存儲區(qū)分配的(有關詳細信息,請參閱 new 和 delete 運算符)。但是,對析構函數的調用可以執(zhí)行相應的清理。若要顯式調用 s 類的對象 String 的析構函數,請使用下列語句之一:

s.String::~String();   // Nonvirtual call
ps->String::~String();  // Nonvirtual call

s.~String();    // Virtual call
ps->~String();   // Virtual call

可以使用對前面顯示的析構函數的顯式調用的表示法,無論類型是否定義了析構函數。這允許您進行此類顯式調用,而無需了解是否為此類型定義了析構函數。顯式調用析構函數,其中未定義的析構函數無效。

相關文章

  • 基于C語言編寫一個簡單的Web服務器

    基于C語言編寫一個簡單的Web服務器

    C語言可以干大事,這篇文章主要為大家詳細介紹了如何基于C語言可以完成一個簡易的Web服務器,希望這篇文章會幫你你對C語言有更深入的理解
    2024-03-03
  • C語言中全局變量,局部變量,靜態(tài)局部變量的區(qū)分方式

    C語言中全局變量,局部變量,靜態(tài)局部變量的區(qū)分方式

    這篇文章主要介紹了C語言中全局變量,局部變量,靜態(tài)局部變量的區(qū)分方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-08-08
  • C指針原理教程之垃圾回收-內存泄露

    C指針原理教程之垃圾回收-內存泄露

    C語言沒有運行時庫,無法自動壓縮使用中的內存,縮小堆棧所需內存空間。若只申請內存,沒有釋放,勢必造成系統(tǒng)內存不斷減少、丟失。長時間的運行,最終導致系統(tǒng)死機。文章闡述了C語言垃圾產生的原因,并從引用計數、標記一清除算法兩方面提出如何實現(xiàn)C語言的垃圾回收。
    2019-02-02
  • 解析C++ 浮點數的格式化輸出

    解析C++ 浮點數的格式化輸出

    本篇文章是對C++中浮點數的格式化輸出進行了詳細的分析介紹,需要的朋友參考下
    2013-05-05
  • 深入分析:C++模板究竟會使代碼膨脹嗎

    深入分析:C++模板究竟會使代碼膨脹嗎

    今天和同事說到C++模板會使代碼膨脹, 可同事覺得不會。 同事的依據是: 如果模板會使代碼膨脹, 那么ATL和WTL里為什么還要大量使用模板? 同樣功能 ,ATL和WTL編譯出的可執(zhí)行文件可比MFC編譯的要小的多
    2013-04-04
  • 實例講解C++ 命名空間

    實例講解C++ 命名空間

    這篇文章主要介紹了C++ 命名空間的的相關資料,文中示例代碼非常詳細,供大家參考和學習,感興趣的朋友可以了解下
    2020-06-06
  • C++與Lua交互原理實例詳解

    C++與Lua交互原理實例詳解

    這篇文章主要介紹了C++與Lua交互原理實例詳解,有感興趣的同學可以研究下
    2021-02-02
  • C語言實現(xiàn)外賣管理系統(tǒng)

    C語言實現(xiàn)外賣管理系統(tǒng)

    這篇文章主要為大家詳細介紹了C語言實現(xiàn)外賣管理系統(tǒng),文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-11-11
  • VC下實現(xiàn)fopen支持中文的方法

    VC下實現(xiàn)fopen支持中文的方法

    這篇文章主要介紹了VC下實現(xiàn)fopen支持中文的方法,需要的朋友可以參考下
    2014-07-07
  • C 語言基礎之C語言的常見關鍵字

    C 語言基礎之C語言的常見關鍵字

    C語言中有一些預先定義的字符串,他們本身被賦予了自身的功能。并且我們在定義變量的時候,不能去搶他們的名字來用。他們就是今天的主角:關鍵字,下面文章將給大家做詳細介紹
    2021-09-09

最新評論

新昌县| 宝坻区| 吉木乃县| 四子王旗| 天祝| 新邵县| 民勤县| 乐山市| 衡阳县| 葫芦岛市| 虹口区| 龙川县| 星座| 环江| 拉萨市| 微山县| 佛教| 白朗县| 黑河市| 聊城市| 临澧县| 嘉峪关市| 壶关县| 庆阳市| 玉树县| 长治县| 织金县| 积石山| 丹江口市| 兖州市| 东方市| 揭西县| 满洲里市| 清涧县| 福鼎市| 孟津县| 和静县| 崇仁县| 湘阴县| 马龙县| 都昌县|