簡體   English   中英

C ++中的析構函數(與java相比)

[英]Destructors in C++ (Compared to java)

到目前為止,我一直在用Java編寫程序。 所以當我開始使用C ++時,首先想到的是如何破壞/刪除/完成我不再需要的對象。

使用Java我曾經將它們設置為null因此垃圾收集器正在處理它。 但是,我不知道C ++的價值。 我發現這篇文章http://en.wikipedia.org/wiki/Comparison_of_Java_and_C%2B%2B解決了我的大部分問題。 但仍有一些我不明白的事情。

1)在Java中有一種方法可以強制垃圾收集器在現場清理(這並不總是有用,因為它在運行之前等待一些垃圾堆疊)。 有沒有辦法用C ++做到這一點?

2)(C ++)與上面相反,我怎樣才能使對象處於“標記為刪除”的狀態,程序決定何時清理它(如Java)?

3)(C ++)我應該強迫垃圾收集器在現場清理(我很確定這不是正確的方式,但我要求確定)?

如果你能給出一個代碼觸發器的小代碼示例,我會贊美它。

1)如果您的對象處於自動存儲中,您可以限制其范圍:

{
   X x;
   //...
}  //x gets destructed here

如果在動態存儲中,則在完成后刪除它們:

X* x = new X;
//...
delete x; //x gets destructed

2)你不能(至少以干凈的方式)。 您必須指示C ++何時刪除對象,即使該指令包含結束括號。 (請參閱第一個代碼段)

3)C ++中沒有垃圾收集器。 看兩個片段。 您必須顯式刪除對象(如果在動態存儲中),或者如果在自動存儲中,它們將被自動刪除(但不會被垃圾收集器刪除)。

值得研究的是智能指針(那里有大量的實現),但這也不是垃圾收集器。 它只是為您節省了管理內存的麻煩。 但它與Java無異。

C ++在這個領域與Java非常不同,所以這里有一個簡短的概述:

分配:為對象留出內存。
結構:准備使用該物體。
破壞:物體“完成”一切並自行拆解。
deallocation:將內存返回給系統。

int main() {
    int myint;  //automatic int object is allocated and constructed
    //stuff
}   // when main ends, automatic int object is destroyed and deallocated

int main() {
    int* mypointer;  //automatic pointer object is allocated and constructed
    mypointer = new int;  //dynamic int object is allocated and constructed
    //stuff
    delete mypointer; //dynamic int object is destroyed and deallocated 
}   // when main ends, automatic pointer object is destroyed and deallocated
    // note: Pointers to _not_ delete the object they point to.

class myclass {
    //members
public:
    myclass() {} //this is the default constructor
    myclass(const myclass& rhs) {} //this is the copy constructor
    myclass& operator=(const myclass& rhs) {return *this} //this is the assignment operator
    ~myclass() {} //this is the destructor
};

當函數結束時,函數本身中的所有變量(我們稱之為自動)都會調用它們的析構函數,然后自動釋放它們。 這意味着對於函數本地的對象,它們會在函數結束的瞬間自動清理。 這也適用於一個類的成員。 當它被銷毀時,它的每個成員都將被自動銷毀。 這意味着大多數析構函數都是空的。

如果手動分配東西(使用new關鍵字),則必須使用delete關鍵字手動銷毀和解除分配。 當你調用delete ,它會在那里銷毀(並解除分配)然后,並且在完成之前不會繼續。 如果你忘記了,它就不會得到DEALLOCATED(盡管如此, 某些操作系統會在你的程序結束時解除分配)。

由於人們會犯錯誤,因此在需要動態對象時要做的“正確”事情是:

int main() {
    std::unique_ptr<myclass> myptr = new myclass(); //allocate and construct
} //both the unique_ptr and the dynamic object are destroyed and deallocated

unique_ptr足夠聰明,可以自動清理它所指向的東西,讓你有更大的顧慮。

C ++這樣做的原因是因為如果你有一個代表該文件的對象F ,它可能對該文件有一個獨占鎖。 在C ++中,一旦F被銷毀,您可以立即創建使用該文件的對象G 在Java中,有沒有保證的finalizer永遠運行,這意味着文件可能會保持鎖定狀態,直到您的程序結束。 (不太可能,但可能)

C ++中沒有垃圾收集器。 你應該自己編寫和運行析構函數。 在C ++中,忘記運行析構函數是一個常見錯誤。

如果你的對象與分配new ,那么你應該刪除它delete 所以, new調用contructor,而delete調用析構函數。

myclass *p = new myclass();
// do something
delete p;

這稱為動態對象分配。

如果您的對象是“正常”定義的,則當超出范圍時它將自動被破壞。

myclass a;
// do something
// will destructed when }

這稱為自動對象分配。

PS你也沒有在Java中分配空值,因為垃圾收集器是為了不打擾刪除對象而發明的。

C ++中的垃圾收集始終是即時的。 沒有單獨的垃圾收集器; 刪除對象時,它會立即刪除當前線程。 它看起來像這樣:

MyObject* foo = new MyObject();
...
delete foo;

有可用於C ++的垃圾收集框架,您還可以查看智能指針,這也是垃圾收集的一種形式。

注意James的評論如下 - 對象的析構函數和操作符刪除總是立即被調用,但它是否依賴於實現,關於內存是否可以立即可用。

C ++使用RAII(資源獲取是初始化)編程習慣,沒有像Java中的垃圾收集器或Objective-C 2中的AutoZone那樣的自動內存管理。因此,正確的實例清理很容易變得復雜。 回答你的問題:

廣告1:C ++中沒有GC,因此您必須手動刪除對象或使用引用計數技術或更好的智能指針,它們現在是C ++ 11標准的一部分,但據我所知它不可用於任何C ++編譯器。 現在,您可以使用Boost庫中的智能指針模板: http//www.boost.org/doc/libs/1_48_0/libs/smart_ptr/smart_ptr.htm 新的C ++標准直接采用了Boost實現,因此在不久的將來切換到新標准時將沒有問題(MSVC 2012將實現C ++ 11支持)。

廣告2:無法標記,只需在正確位置“手動”刪除它或將此任務留在智能指針上。

廣告3:不適用。

最后,始終有最簡單的選項 - 不要在堆上分配對象,這意味着動態。 在Java中沒有這種可能性,但在C ++中有。 我甚至讀過一些關於C ++編程的Stroustrup(C ++的創建者)的好書,在C ++創建時,不推薦這樣的動態分配。 他說:要讓RAII正常工作,一定不能進行動態分配 - 今天聽起來很奇怪,但這就是Stroustrup所寫的,它不是我的頭腦,我個人動態分配幾乎所有人都做的事......

靜態分配的主要原因是,一旦超出范圍,對象就會被刪除,因此根本不必擔心異常安全和清理。 如果您動態分配實例,則如果實例離開當前范圍,則不會自動刪除它 - 如果您沒有手動刪除實例,則會發生內存泄漏。 考慮一下簡單的try-catch塊:

try 
{
Class *instance = new Class;
//some error
}
catch(...)
{
//error caught - current execution is terminated immediately, instance is no deleted - memory leak.
}

我在Java中有一個始終被調用的finally語句,因此您可以在拋出異常時執行必要的清理。 但是在C ++中你遇到麻煩... 除非你使用提到的智能指針或一些非常類似的技術。當使用智能指針時你不必再擔心清理了(在實踐中不完全正確,但你的生活肯定會是更容易,你的代碼更少的bug)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM