2010-03-23 82 views
12

析構函數是否釋放分配給它所屬對象的內存,或者它是否只是被調用,以便它可以在編譯器釋放對象之前執行最後一分鐘的內務管理?C++中的析構函數

+2

析構函數應該刪除析構函數的對象持有的任何動態分配的對象,但析構函數不負責釋放其對象所在的內存。 – 2010-03-23 17:45:50

回答

32

'編譯器'不會刪除任何內容。它創建在運行時執行任務的代碼。

當你寫delete somePointer;編譯器,在本質上寫道:

if (has_virtual_destructor(* somePointer )) { 
     // virtual dispatch to a compiler-generated function 
     dynamic_cast< true_dynamic_type * >(somePointer)->destroy_dynamic_type(); 
     /* contents of true_dynamic_type::destroy_dynamic_type() { 
       this->~true_dynamic_type(); 
       operator delete(this); // executed within class context 
     } */ 
    } else { 
     somePointer->~ClassName(); 
     operator delete(somePointer); 
    } 

換句話說,析構函數被調用,然後刪除操作被調用,以釋放存儲空間。

如果析構函數是虛擬的,則使用虛擬分派以其派生最多的形式對對象執行整個操作。實現這一點的常用方法是向每個虛擬析構函數添加隱藏的參數。

請注意,頂級if語句實際上不是生成的代碼的一部分;編譯器在編譯時做出該決定。

+1

這是很多upvotes; v)...也許提到演員爲真正的動態在虛擬析構函數的情況下輸入。 (而且,'operator delete'查找的工作方式,'delete'實際上是在一個「負責任的」虛擬析構函數中調用的,沒有提到這可能會導致配置文件跟蹤混淆。) – Potatoswatter 2010-03-23 19:16:08

+0

@potatoswatter:感覺編輯。我無法解釋山體滑坡,我只是輸入了明顯的信息。 – bmargulies 2010-03-24 11:41:04

+0

一個小小的挑剔:這個'if(has_virtual_destructor ...'不是*在運行時執行。*編譯器*可以決定每種類型(因此只取決於* static *類型)它是否有虛擬或非虛擬析構函數並且爲這兩種情況發出適當的代碼不知道當你試圖刪除一個void *時會發生什麼,但我的猜測是這將會是UB – 2010-05-21 09:18:46

2

調用析構函數以允許對象執行清理以及銷燬對象本身創建的任何其他對象。

操作系統將處理完成析構函數後釋放對象本身。

0

1)析構函數不屬於對象,它屬於

2)它爲它的類中的所有用戶定義的類型(類對象)調用析構函數。

3)清除是,如果確實需要

0

它的內存析構函數退出後,再返回執行「刪除」打電話或點對象實例進入前右釋放它僅完成可選活動超出範圍。理論上可以設置不同的內存管理器來處理新的和刪除,但這是默認行爲的顯式變化。

0

更具體地說,除了程序員之外,沒有人能夠在C++中釋放內存。如果對象位於堆棧上,它駐留在程序的內存空間中,並在程序的生命週期中佔用空間。如果它在堆上,則創建該對象的人負責將其釋放。那是什麼delete確實。這將我們帶入析構函數 - 如果您在類中創建對象,析構函數允許您在類離開作用域時將其刪除。它可以讓你「在離開時熄燈」。

+0

沒有「程序員」。如果我是程序員,用類型爲std :: vector的成員變量編寫一個類,我不需要,也不要寫co刪除它。編譯器會自動生成代碼來調用std :: vector析構函數,這是某個其他程序員在某個時間編寫的,並在頭文件中提供。 – 2010-03-23 17:55:25

+0

即使不是專門爲你設置「程序員」,計算機也不會殺人,人們會殺人。或者泄漏記憶,不管。如果你創建了std :: vector的成員變量,那麼它就在堆棧中。沒有分配,沒有責任。如果你的std :: vector在內部分配堆內存,那麼在這種情況下,「程序員」就是std :: vector的程序員,而不是你,所以你不必擔心它。 – Matt 2011-09-29 21:23:12

0

析構函數自動調用被銷燬對象的成員變量的析構函數。那些析構函數可能會或可能不會釋放內存。但是,指針沒有析構函數,或者如果你願意,指針的析構函數什麼也不做。它沒有釋放它指向的內存。如果一個對象包含一個指向從「new」或「malloc」獲得的對象的指針,那麼由該對象的程序員決定使析構函數做正確的事情。如果它在概念上被破壞的對象的一部分,你應該編程你的析構函數來「刪除」或「釋放」內存。例如,一個「向量」對象通常從堆中獲得內存,因爲所需的內存量在編譯時通常是不知道的。該內存在概念上是矢量對象的一部分,因此矢量類的程序員必須在析構函數中調用它的「刪除」。像std :: vector這樣的標準模板庫類可以正確執行。

另一方面,一些對象包含對其他對象的引用。字典或索引將包含對概念上不屬於它們的對象的引用(指針)。該內存不能被析構函數釋放。 (如果您從電話簿中刪除電話號碼,則不希望電話自動消失。)

有一些例外,初學者不需要關心。一種是當對象及其容器被編程爲使用引用計數,並且引用的對象在引用它的最後一個對象允許它去之前並不真正釋放。另一個例外是「放置新」的情況。