<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                # [11] 析構函數 ## FAQs in section [11]: * [11.1] 析構函數做什么? * [11.2] 局部對象析構的順序是什么? * [11.3] 數組中的對象析構順序是什么? * [11.4] 我能重載類的析構函數嗎? * [11.5] 我可以對局部變量顯式調用析構函數嗎? * [11.6] 如果我要一個局部對象在其被創建的代碼塊的 } 之前被析構,如果我真的想這樣,能調用其析構函數嗎? * [11.7] 好,好;我不顯式調用局部對象的析構函數;但如何處理上面那種情況? * [11.8] 如果我無法將局部對象包裹于人為的塊中,怎么辦? * [11.9] 如果我是用 `new` 分配對象的,可以顯式調用析構函數嗎? * [11.10] 什么是“定位放置 `new`(placement `new` )”,為什么要用它? * [11.11] 編寫析構函數時,需要顯式調用成員對象的析構函數嗎? * [11.12] 當我寫派生類的析構函數時,需要顯式調用基類的析構函數嗎? * [11.13] 當析構函數檢測到錯誤時,可以拋出異常嗎? ## 11.1 析構函數做什么? 析構函數為對象舉行葬禮。 析構函數用來釋放對象所分配的資源。舉例來說,`Lock` 類可能鎖定了一個信號量,那么析構函數將釋放該信號量。最常見的例子是,當構造函數中使用了`new`,那么析構函數則使用`delete`。 析構函數是“準備后事”的成員函數。經常縮寫成“dtor”。 ## 11.2 局部對象析構的順序是什么? 與構造函數反序:先被構造的,被后析構。 以下的例子中,`b`的析構函數會被首先執行,然后是 `a` 的析構函數: ``` ?void?userCode() ?{ ???Fred?a; ???Fred?b; ???//?... ?} ``` ## 11.3 數組中的對象析構順序是什么? 與構造函數反序:先被構造的,后被析構。 以下的例子中,析構的順序是`a[9]`, `a[8]`, ..., `a[1]`, `a[0]`: ``` ?void?userCode() ?{ ???Fred?a[10]; ???_//?..._ ?} ``` ## 11.4 我能重載類的析構函數嗎? 不行。 類只能有一個析構函數。`Fred` 類的析構函數能是`Fred::~Fred()`。不帶任何參數,不返回任何東西(譯注:void也不行)。 由于你不會顯式地調用析構函數(是的,永遠不會),因此無論如何不能傳遞參數給析構函數。 ## 11.5 我可以對局部變量顯式調用析構函數嗎? 不行! 在創建該局部對象的代碼塊的 `}` 處,析構函數會自動被調用。這是語言所保證的;自動發生。沒有辦法阻止它。而兩次調用同一個對象的析構函數,你得到的真是壞的結果!砰!你完蛋了! ## 11.6 如果我要一個局部對象在其被創建的代碼塊的 `}`之前被析構,如果我真的想這樣,能調用其析構函數嗎? 不行!詳見 [前一個FAQ]. 假設析構 `File` 對象的作用是關閉文件。現在假定你有一個 `File`類的對象 `f`,并且你想 `File` `f` 在 `f` 對象的作用范圍結束(也就是 `}` )之前被關閉: ``` ?void?someCode() ?{ ???File?f; ???//?...?[這些代碼在 f 打開的時候執行]?... //?<—?希望在此處關閉 f //?...?[這些代碼在 f 關閉后執行]?... ?} ``` 對這個問題有一個簡單的解決方案。但現在請記住:_不要顯式調用析構函數!_ ## 11.7 好,好;我不顯式調用局部對象的析構函數;但如何處理上面那種情況? 內容詳見 [前一個 FAQ]. 只要將局部對象的生命期長度包裹于一個人為的 `{`...`}` 塊中: ``` ?void?someCode() ?{ ???{ ?????File?f; ?????//?...?[這些代碼在 f 打開的時候執行]?... ???} ? //?^—?f?的析構函數在此處會被自動調用! //?...?[這些代碼在 f 關閉后執行]?... ?} ``` ## 11.8 如果我無法將局部對象包裹于人為的塊中,怎么辦? 大多數時候,你可以通過將局部對象包裹于人為的`{`...`}`塊中,限制其生命期。但如果由于一些原因無法這樣做,則增加一個模擬析構函數作用的成員函數。但_不要調用析構函數本身_! 例如,`File`類的情況下,可以添加一個`close()`方法。典型的析構函數只是調用`close()`方法。注意`close()`方法需要標記 `File` 對象,以便后續的調用不會再次關閉一個已經關閉的文件。舉例來說,可以將一個`fileHandle_`數據成員設置為 -1,并且在開頭檢查`fileHandle_`是否已經等于-1: ``` ?class?File?{ ?public: ???void?close(); ???~File(); ???//?... ?private: ???int?fileHandle_;???//?當且僅當文件打開時 fileHandle_?>=?0 ?}; ?File::~File() ?{ ???close(); ?} ?void?File::close() ?{ ???if?(fileHandle_?>=?0)?{ ?????//?...?[執行一些操作-系統調用來關閉文件]?... ?????fileHandle_?=?-1; ???} ?} ``` 注意其他的 `File`方法可能也需要檢查`fileHandle_`是否為 -1(也就是說,檢查文件是否被關閉了)。 還要注意任何沒有實際打開文件的構造函數,都應該將`fileHandle_`設置為 -1。 ## 11.9 如果我是用`new`分配對象的,可以顯式調用析構函數嗎? 可能不行。 除非你使用定位放置 `new`,否則應該 `delete` 對象而不是顯式調用析構函數。例如,假設通過一個典型的 `new` 表達式分配一個對象: ``` Fred*?p?=?new?Fred(); ``` 那么,當你`delete`它時,析構函數 `Fred::~Fred()` 會被調用: ``` delete?p;??//?自動調用?p->~Fred() ``` 由于顯式調用析構函數不會釋放 `Fred` 對象本身分配的內存,因此不要這樣做。記住:`delete?p` 做了兩件事情:調用析構函數,回收內存。 ## 11.10 什么是“定位放置`new`(placement `new`)”,為什么要用它 ? 定位放置`new`(placement `new`)有很多作用。最簡單的用處就是將對象放置在內存中的特殊位置。這是依靠 `new`表達式部分的指針參數的位置來完成的: ``` ?#include?<new>????????//?必須?#include?這個,才能使用?"placement?new" ?#include?"Fred.h"?????//?class?Fred 的聲明 ?void?someCode() ?{ ???char?memory[sizeof(Fred)];?????//?Line?#1 ???void*?place?=?memory;??????????//?Line?#2 ???Fred*?f?=?new(place)?Fred();???//?Line?#3?(詳見以下的“危險”) //?The?pointers?f?and?place?will?be?equal //?... ?} ``` Line #1 在內存中創建了一個`sizeof(Fred)`字節大小的數組,足夠放下 `Fred` 對象。Line #2 創建了一個指向這塊內存的首字節的`place`指針(有經驗的 C 程序員會注意到這一步是多余的,這兒只是為了使代碼更明顯)。Line #3 本質上只是調用了構造函數 `Fred::Fred()`。`Fred`構造函數中的`this`指針將等于`place`。因此返回的 `f` 將等于`place`。 建議:萬不得已時才使用“placement `new`”語法。只有當你真的在意對象在內存中的特定位置時才使用它。例如,你的硬件有一個內存映象的 I/O計時器設備,并且你想放置一個`Clock`對象在那個內存位置。 危險:你要獨自承擔這樣的責任,傳遞給“placement `new`”操作符的指針所指向的內存區域必須足夠大,并且可能需要為所創建的對象進行邊界調整。編譯器和運行時系統都不會進行任何的嘗試來檢查你做的是否正確。如果 `Fred`類需要將邊界調整為4字節,而你提供的位置沒有進行邊界調整的話,你就會親手制造一個嚴重的災難(如果你不明白“邊界調整”的意思,那么就不要使用placement `new`語法)。 你還有析構放置的對象的責任。這通過顯式調用析構函數來完成: ``` ?void?someCode() ?{ ???char?memory[sizeof(Fred)]; ???void*?p?=?memory; ???Fred*?f?=?new(p)?Fred(); ???//?... ???f->~Fred();???//?顯式調用定位放置的對象的析構函數 ?} ``` 這是顯式調用析構函數的唯一時機。 ## 11.11 編寫析構函數時,需要顯式調用成員對象的析構函數嗎? 不!永遠不需要顯式調用析構函數(除了定位放置 `new`的情況)。 類的析構函數(不論你是否顯式地定義了)自動調用成員對象的析構函數。它們以出現在類聲明中的順序的反序被析構。 ``` ?class?Member?{ ?public: ???~Member(); ???//?... ?}; ?class?Fred?{ ?public: ???~Fred(); ???_//?..._ ?private: ???Member?x_; ???Member?y_; ???Member?z_; ?}; ?Fred::~Fred() ?{ ???//?編譯器自動調用?z_.~Member() //?編譯器自動調用?y_.~Member() //?編譯器自動調用?x_.~Member() ?} ``` ## 11.12 當我寫派生類的析構函數時,需要顯式調用基類的析構函數嗎? 不!永遠不需要顯式調用析構函數(除了定位放置 `new`的情況)。 派生類的析構函數(不論你是否顯式地定義了)自動調用基類子對象的析構函數。基類在成員對象之后被析構。在多重繼承的情況下,直接基類以出現在繼承列表中的順序的反序被析構。 ``` ?class?Member?{ ?public: ???~Member(); ???//?... ?}; ?class?Base?{ ?public: ???virtual?~Base();?????//?虛析構函數 //?... ?}; ?class?Derived?:?public?Base?{ ?public: ???~Derived(); ???//?... ?private: ???Member?x_; ?}; ?Derived::~Derived() ?{ ???//?編譯器自動調用?x_.~Member() //?編譯器自動調用?Base::~Base() ?} ``` 注意:虛擬繼承的順序相關性是多變的。如果你在一個虛擬繼承層次中依賴于其順序相關性,那么你需要比這個FAQ更多的信息。 ## 11.13 當析構函數檢測到錯誤時,可以拋出異常嗎? 謹防!!! 詳見 該 FAQ。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看