2011-09-19 78 views
4

我有我的程序中的許多對象使用的全球單身人士。當程序關閉時,這會導致崩潰 - 在單例本身被程序結束破壞之後,它被用在某些對象的析構函數中。有沒有一種可移植的方式來判斷一個指針是否已經調用了'delete'?就我而言,它看起來像刪除將指針的值更改爲(void *)( - 1),但我不知道這是否便攜。你可以告訴C++指針是否已被破壞?

+6

沒有,沒有,你不應該。查看「singleton antipattern」和「static initialization hell」。 –

+0

'delete'不應該改變你的指針的值。 –

+0

最有可能是在調試版本 –

回答

6

不,這是不可能告訴我們,如果指向的對象++指針已經被破壞的C值。

您可以使用自動處理它的智能指針。

+0

這對於銷燬順序並不真正有幫助儘管單身。 –

+0

@AndréCaron:的確如此,但是除非語言變化無所適從。 –

+2

看起來問題在於設計。 –

0

不可能,我原以爲這是一個未定義的區域。

你最好的辦法是不要刪除單後才一切已經被清理乾淨,否則刪除實例後,指針設置爲NULL,然後您可以檢查這一點。這聽起來像一些重構是爲了儘管。

0

正如之前所說,不,你不能。有不同的技術來跟蹤這一點,但它們依賴於平臺。

首先,你的情況下的實際問題是什麼?你有一個單身,在被銷燬時被其他物體使用。如果你的單例被C運行時破壞,那麼破壞其他對象呢?

+0

C運行時也破壞了其他對象,就在這之後 –

+0

因此,我在這裏看到設計問題:C運行時沒有保證析構函數的特定順序。檢查單例是否被破壞是一種破解,而不是一個合適的解決方案。單身人士的做法是什麼? –

0

一種簡單的方法來確定什麼是刪除單是簡單的化妝單身的析構函數私有。然後,您應該在試圖刪除它的任何地方收到編譯錯誤。

1

簡單的答案:

  • 不使用指針。
  • 使用經典的邁爾斯單身。

然後爲了保證它在對象剛剛確定它在對象之前被實例化之後被銷燬。爲了確保它在對象剛剛在對象的構造函數中使用之前被實例化。

經驗法則:如果你想在析構函數中使用單例。首先在構造函數中使用它。

class A 
{ 
    A(); 
    A(A const&); 
    A& operator=(A const&); 
    public: 
     static A& getInstance() // return reference. 
     { 
      static A instance; // Created on first use. 
           // So lazily created when expensive. 

      return instance; // Guaranteed to be destroyed in reverse order of 
           // creation In comparison to other static storage 
           // duration objects. Thus if it is created before 
           // your object It is guaranteed to be correctly 
           // destroyed after your object. 

           // If you want to guarantee it is created before your 
           // object just call A::getInstance() in your constructor 
           // the static member 'instance' will only be created 
           // once and returning a reference is not expensive. 
     } 
     // If you are creating this from the constructor of a global 
     // Then threading becomes a non issues as threads are not started before main 
     // If you are using pthreads or Windows threads you potentially can start them 
     // but it is undefined if they will work so again not your issue. 
}; 
0

此代碼將跟蹤靜態實例的生命週期;如果你分配的話,工作同樣好。 當然,即使實例尚未構建,它也會在第一次調用instance()時發生。 但是,如果你有一些複雜的全局靜態析構函數,你應該可以使用它來確定實例是否被破壞。

class Thing 
{ 
public: 
    enum State { preConstruction, constructed, destructed }; 
    static const State& singletonState() { return state_;} 
    static Thing& instance() 
    { 
     static Thing instance; 
     return instance; 
    } 
private: 
    Thing() 
    { 
     state_ = constructed; 
    } 
    ~Thing() 
    { 
     state_ = destructed; 
    } 
    static State state_; 
}; 

Thing::State Thing::state_ = Thing::preConstruction; 
相關問題