[英]Destructing a Single shared_ptr One-by-One
我試圖一個一個地破壞 shared_ptr,但是當我破壞最后一個指針時, use_count() 變得瘋狂。 觀察我的代碼:
#include <iostream>
#include <memory>
int main() {
int * val = new int(5);
std::shared_ptr<int> myPtr = std::make_shared<int>(*val);
myPtr.~__shared_ptr();
}
將在調試器中產生以下輸出:
myPtr value: 5 myPtr.use_count():8787448 // Or some other large int
我希望在最終銷毀時它將 use_count() 設置為 0 並釋放整數的內存。 似乎這一切都沒有發生。
當 use_count() == 1 時,我可以 if() 聲明這個,但這看起來很不雅觀。 有誰知道另一種解決方案?
我試圖一個一個地破壞一個 shared_ptr,
我不知道那是什么意思,但是......
myPtr.~__shared_ptr();
永遠,永遠,永遠不要這樣做。
您正在為一個自動對象運行析構函數,即一個存在於堆棧中的對象,當它超出范圍時將被編譯器自動銷毀。 通過手動銷毀它,您會導致它被銷毀兩次。 你不能兩次結束一個物體的生命周期,它不是詹姆斯邦德,它只存在一次。
兩次銷毀同一個對象是未定義的行為。 這意味着可能會發生奇怪的事情。 詢問為什么您從具有未定義行為的程序中得到奇怪的結果是浪費時間。 當您有未定義的行為時會發生奇怪的事情,因為您有未定義的行為。 任何事情都可能發生。 你應該慶幸這只是奇怪,而不是災難性的。
該標准在 12.4 [class.dtor] 中特別指出這種情況是未定義的行為:
一旦為一個對象調用了析構函數,該對象就不再存在; 如果為生命周期已結束 (3.8) 的對象調用析構函數,則行為未定義。 [示例:如果顯式調用自動對象的析構函數,並且塊隨后以通常會調用對象的隱式析構的方式留下,則行為未定義。 — 結束示例]
更糟糕的是,您正在為myPtr
的基類運行析構函數,因此您只是在破壞對象的一部分。 這意味着你有一個對象,它的一部分是死的,一部分是活的,然后在作用域結束時它的一部分再次被殺死。 在任何情況下,這都不是正確的做法。 曾經。
我希望在最終銷毀時它將 use_count() 設置為 0 並釋放整數的內存。 似乎這一切都沒有發生。
你的結論是錯誤的。 它可能正在發生,但是如果對象被銷毀並且內存被釋放,那么嘗試查看它會產生無意義的結果。 你不能問僵屍它的名字是什么,它會回答“BRAINZZZZ!” 而不是告訴你任何有用的東西。 並吃掉你的大腦。 現在你死了。 不要玩僵屍。
此外,正如 Neil Kirk 上面評論的那樣,這也是錯誤的:
int * val = new int(5);
std::shared_ptr<int> myPtr = std::make_shared<int>(*val);
您在堆上創建一個int
,然后在由shared_ptr
管理的堆上創建它的副本。 shared_ptr
擁有一個int
,它與*val
具有相同的值,但沒有任何東西擁有val
因此這將是內存泄漏。 您可能打算這樣做:
int * val = new int(5);
std::shared_ptr<int> myPtr(val);
或更可能是這樣:
int val = 5;
std::shared_ptr<int> myPtr = std::make_shared<int>(val);
我想我知道你在追求什么。 您想檢測共享對象的使用計數何時為零。
這樣做的方法是使用std::weak_ptr設計為與std::shared_ptr 一起使用,以便您可以跟蹤對象是否已被銷毀。
這里:
#include <memory>
#include <iomanip>
#include <iostream>
int main()
{
// weak_ptr is only convertable to a shared_ptr if the shared_ptr
// usage count is > 0
std::weak_ptr<int> wp;
{
std::shared_ptr<int> ptr = std::make_shared<int>(5);
wp = ptr; // link weak_ptr to shared_ptr
if(auto sp = wp.lock()) // try to convert weak_ptr to shared_ptr
{
// if we get here use_count was > 0
std::cout << "Before: use count > 0: "
<< std::boolalpha << (sp.use_count() > 0) << '\n';
}
else
{
// if we get here use_count was == 0
std::cout << "Before: Destroyed\n";
}
// ptr goes out of scope here
}
if(auto sp = wp.lock()) // try to convert weak_ptr to shared_ptr
{
// if we get here use_count was > 0
std::cout << "After: use count > 0: "
<< std::boolalpha << (sp.use_count() > 0) << '\n';
}
else
{
// if we get here use_count was == 0
std::cout << "After: Destroyed\n";
}
}
基本上,如果鏈接的std::shared_ptr仍然持有對對象的引用,那么關聯的std::weak_ptr可以使用std::weak_ptr::lock轉換為std::shared_ptr 。 如果失敗,則關聯的std::shared_ptr不再指向共享對象 - 它已被銷毀。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.