我有一個對象,裏面有一些指針。析構函數在這些指針上調用delete
。但有時我想刪除它們,有時我不會。所以我希望能夠刪除對象而不用調用析構函數。這可能嗎?是否有可能在不調用析構函數的情況下刪除C++中的對象?
編輯:我意識到這是一個很好的想法,沒有人應該做。不過,我想這樣做,因爲它會使一些內部函數更容易編寫。
我有一個對象,裏面有一些指針。析構函數在這些指針上調用delete
。但有時我想刪除它們,有時我不會。所以我希望能夠刪除對象而不用調用析構函數。這可能嗎?是否有可能在不調用析構函數的情況下刪除C++中的對象?
編輯:我意識到這是一個很好的想法,沒有人應該做。不過,我想這樣做,因爲它會使一些內部函數更容易編寫。
您可以將指針設置爲NULL,那麼析構函數將不會刪除它們。
struct WithPointers
{
int* ptr1;
int* ptr2;
WithPointers(): ptr1(NULL), ptr2(NULL) {}
~WithPointers()
{
delete ptr1;
delete ptr2;
}
}
...
WithPointers* object1 = new WithPointers;
WithPointers* object2 = new WithPointers;
object1->ptr1 = new int(11);
object1->ptr2 = new int(12);
object2->ptr1 = new int(999);
object2->ptr2 = new int(22);
...
int* pointer_to_999 = object2->ptr1;
object2->ptr1 = NULL;
delete object1;
delete object2; // the number 999 is not deleted now!
// Work with the number 999
delete pointer_to_999; // please remember to delete it at the end!
它忘記了未來的繁榮。使用武力,並提防黑暗! – 2013-02-14 18:14:16
我應該想到這個簡單的伎倆。謝謝。 – 2013-02-14 18:58:19
@MichaelDorgan:如果他忘記了它並不是一個問題,那麼它會變得繁榮:他會發現它並糾正它。 「黑暗的一面」是不正確的東西,但不要繁榮! (你永遠不會知道,直到用戶有一天會看到不正確的東西) – 2013-02-14 20:08:16
Eww!是的,這是可能的,不,我不會這樣做。通過共享指針或其他引用計數對象來控制需要變量生存期的對象。使用C++的清潔工比打破其內部租戶的一些清潔工...
我知道這是做到這一點的正確方法,但我想以各種理由按我的方式去做。這不是公開暴露的功能,而是內部使用的一些功能,使得幾個功能更簡單。 – 2013-02-14 18:07:23
我建議你不要去那裏。誰知道,在未來,其他人會走進你的代碼,並推動一些東西和繁榮。或者也許是一個新的編譯器版本等。違反規則使得很難調試某些東西,因爲在查看代碼時,解決方案不會成爲頭20件事情。 – 2013-02-14 18:11:36
它可能會使某些內部函數「易於編寫」(有爭議),但它*當然*不會使它們更安全或更容易*維護*。任何人在你認爲你瘋了之後看着這段代碼。 – meagar 2013-02-14 18:18:10
無論你真的想要做什麼,你的代碼都有問題。 如果您不想刪除子對象,只需使用布爾標誌,您將在刪除對象之前設置該標誌,並且析構函數會將其考慮在內。
但說實話,你應該使用智能指針而不是裸指針(在你的情況下,它看起來像共享指針是你所需要的)。
正如其他人所說的,解決這個問題的正確方法不是調用析構函數[你只需要在對象中添加諸如std::string
或std::vector
之類的內容,並且突然間你有內存泄漏] 。正確的方法是讓對象根本不擁有這些其他對象(例如,在對象被刪除之前/之後單獨刪除它們),或者讓對象知道是否刪除指針。
編寫一個在調用析構函數之前可以調用的方法。該方法將翻轉成員布爾值。當調用destuctor時,它將檢查該布爾成員,並在指針爲真時銷燬指針,如果該指針爲false,則保留該指針。
我不會推薦這樣做。最好不要爲刪除指針負責。
是的,這是可能的。 std::vector
是這樣做的,因爲它爲緩衝區分配了緩衝空間,然後有條件地構造緩衝區(in-place)並銷燬它們,獨立於對象生命週期管理內存。在C++ 11中,我會使用您的類型的union
和一個帶有簡單的構造函數/析構函數的小類型來指示一個可以適合您的類型的內存位置,但不必在其中包含該類型。外在的,你必須跟蹤對象是否真的存在。創建項目包括使用放置new
,並銷燬它包括手動調用析構函數。
union
對象的緩衝區,無論是N個對象還是1個,都將完全獨立管理。 union
的默認構造函數將構造任何東西,或構造平凡類型(在這種情況下,您可能想要銷燬該平凡類型)。
但是,您的問題的真正答案是「不要這樣做」。如果你這樣做,你將指針包裝在class
的只有工作正在處理上述混亂。該類型的類(其作用是管理指針的生命期和指針狀屬性)稱爲「智能指針」。
的delete
運營商做了兩件事對象傳遞給它:
operator delete
。所以刪除對象,而不調用析構函數意味着你要簡單地調用operator delete
的對象:
Foo *f = new Foo;
operator delete(f);
operator delete
是一個正常的函數調用和通常的名稱查找和重載解析完成。但delete
運營商有其自己的規則找到正確的operator delete
。例如,delete
運算符將查找會員operator delete
通用名稱查找和重載解析無法找到的函數。這意味着當您手動使用operator delete
時,您需要確保您正在調用正確的功能。
正如你所說,直接使用operator delete
是一個可怕的想法。未能調用析構函數會中斷RAII,導致資源泄漏。它甚至可能導致未定義的行爲。此外,您必須承擔編寫異常安全代碼而不使用RAII的責任,這非常困難。你幾乎可以保證弄錯了。
'delete f'實際上是'f->〜Foo();運算符delete(f);'(就像'new Foo'實際上'new(operator new(sizeof(Foo)))Foo')。那些「*從構造/銷燬*中脫離分配/釋放」的形式很少見,但是當內存的歷史不遵循它所持有的對象的歷史時會發生。這通常是在例如std :: vector實現中找到的。 – 2013-02-15 08:42:17
@EmilioGaravaglia我相信你只是重複我所說的一部分。我沒有看到你提出的更正,如果有的話。 – bames53 2013-02-15 15:16:11
這不是一個修正:只是關於相應的放置new/operator new的補充,關於這個構造經常在標準庫內部發生 – 2013-02-15 15:21:49
所以問題是如何使動態分配的對象以不需要顯式調用'delete' /'free'的方式釋放? – LihO 2013-02-14 18:07:53
@LihO是的。或者,在不調用析構函數的情況下調用'delete' /'free'。 – 2013-02-14 18:10:25
那麼,只需將這些內部指針設置爲'nullptr',然後'刪除它們將是一個空操作。 – 2013-02-14 18:10:52