2017-02-08 40 views
2

A C++ std::shared_ptr<..>可能是並且它也可能是null。這兩個概念都存在,它們是而不是等效。另外,在這些情況之間,暗示總是如此。如何測試shared_ptr是否爲空或者什麼都不擁有

後一種情況很容易檢測,因爲operator bool提供了精確的測試。根據文檔,它「檢查*this是否存儲非空指針,即是否get() != nullptr」。

是否有在前一種情況下,一個測試,其中一點是的情況?

我對此的使用很簡單。我有一個擁有靜態工廠方法的類。靜態工廠方法內部是一個靜態本地shared_ptr到類的一個實例,初始化爲nullptr。對這個工廠方法的第一次調用構造了一個類的實例,並在返回它的一個副本之前初始化靜態本地shared_ptr - 這由mutex來保護。 shared_ptr可能被任何東西持有,被複制並傳遞過來,進一步的副本可能通過對靜態工廠的額外調用而獲得,最後,當所有副本被破壞時,shared_ptr的刪除程序破壞該實例。

實例本身是用我的類包裝的傳統C API創建和破壞的,儘管這些實例旨在作爲單例共享,但是當它們不再需要時,它們也需要清理 - 不像單身。

目前,我正在使用空檢查來決定靜態本地shared_ptr應該被初始化還是僅僅被複制。我害怕這個測試無法檢測到需要重新初始化的情況 - 例如,如果在所有先前的用戶放棄其引用並且共享實例被刪除之後某些事情試圖獲取實例。

或者是否確實shared_ptr被重置爲nullptr當引用計數下降到零並且刪除器被調用?還針對自定義刪除者?

另外相關:What is the difference between an empty and a null std::shared_ptr in C++?

+1

如何檢查,如果[計數器(http://en.cppreference.com/w/cpp/memory/shared_ptr/use_count)爲零? –

+0

由於註釋:「但是,這在多線程環境中不能保證。」 – Xharlie

+2

當我讀到這個時,聽起來好像第一次初始化發生後,對於某個shared_ptr對象總是有一個引用計數1。如果不是的話,你會用這個假設的電話來確定它的當前狀態是什麼目的? 聽起來你可能想要weak_ptr行爲。或者,也許你可以澄清這個問題,以使這一點更加清楚(即「在所有先前的用戶放棄其引用並且共享實例被刪除後的某個時候嘗試獲取實例的情況」)。 – cnettel

回答

5

shared_ptr的靜態實例將持有的引用,因此該對象將總是有一個ref計數> = 1,直到靜態清理髮生不會被刪除。正如cnettel在評論中所說,你需要std::weak_ptr在這裏。

weak_ptr基本上是shared_ptr,它不參與ref計數。它通過.lock()方法將原子投射到std::shared_ptr。如果結果爲std::shared_ptr未被初始化,則將轉換爲false,因此您知道要重新初始化(或初次初始化)。

實施例:

std::shared_ptr<Obj> instance() { 
    static std::weak_ptr<Obj> instance; 
    static std::mutex lock; 

    std::lock_guard<std::mutex> guard(lock); 

    auto result = instance.lock(); 
    if (!result) { 
     result = std::make_shared<Obj>(); 
     instance = result; 
    } 

    return result; 
} 
+0

Alrighty。我想我現在有我目前需要的東西。但我仍然不知道我*問的實際問題的答案。似乎沒有線程安全的解決方案來解決*這個問題......這對我來說很好,因爲我不再需要它了。助教。 – Xharlie

+0

所述問題的問題是,一旦初始化shared_ptr就永遠不會有一個計數<= 0,所以問題中的前提條件永遠不會發生。檢查計數器是否爲零隻是檢查它是否已初始化,我認爲警告基本上是說'if(ptr.use_count()== 0)ptr = new Obj();'不是線程安全的,並且你需要一個互斥體。 –

+0

也檢查null(即默認操作符布爾)應該始終是您的有效性檢查。您不應(通常)關心shared_ptr擁有的內容。它可能擁有一個包含對象,或者甚至沒有任何東西(例如指向堆棧),但是如果它解除引用nullptr,就不能使用它,所以你應該像這樣做是無效的。從技術上講,我想你可以有一個指針自己的東西,但實際上取消引用null,但這必須非常奇怪地明確構造,我個人不能想象它的用途。 –

相關問題