2014-03-12 201 views
0

我有兩個單例類。從一個班級到另一個班級是否安全?

第一個人持有對第二個成員的引用。

#include <memory> 

class B 
{ 
    friend class A; 
    public: 
     static B& getInstance() 
     { 
      static B instance; 

      return instance; 
     } 
    private: 
     B() 
     : b(new int(5)) 
     , c(8) 
     {}; 
     B(B const&); 
     void operator=(B const&); 

     private: 
      std::auto_ptr<int> b; 
      int c; 
}; 


class A 
{ 
    public: 
     static A& getInstance() 
     { 
      static A instance; 

      return instance; 
     } 
    private: 
     A() 
     : b(B::getInstance().b.get()) 
     , cRef(B::getInstance().c) 
     { 
     }; 
     A(A const&); 
     void operator=(A const&); 
     private: 
      int* b; 
      int& cRef; 
}; 

int main() 
{ 
    return 0; 
} 

此代碼是否安全?

+0

此代碼是100%安全的,因爲它什麼都不做。用這些類的用法填充'main()'。具體而言,我們感興趣的是您將調用哪種順序的方法。 (這是第一個不安全的地方,因爲你需要告訴用戶如何正確使用你的類,接口必須以某種方式設計,不允許以錯誤的方式使用它) – Drop

回答

2

我想是的。這兩個實例都從第一次訪問開始直到程序的整個生命週期。唯一可能會變得棘手的是破壞:如果A的析構函數使用了B的引用/指針,但B已經被銷燬了。幸運的是,在3.6.3標準保證(援引2012年草案):

「如果構造或 動態初始化的完成具有靜態存儲持續時間的對象是之前的 另一測序,在第一個析構函數開始之前,第二個析構函數的完成順序爲 。「

(我強調)換句話說,破壞的逆序是爲靜態對象保證的。由於您的施工順序良好,銷燬順序也是如此。 A的引用/指向B的指針將在整個A的實例銷燬中有效。

0

這裏你沒有對對象數據做任何事情,所以這段代碼在單線程環境中是正確的。在多線程添加鎖定到某個getInstance()方法:

static A& getInstance() { 
     Lock lock; 
     static A instance; 
     return instance; 
    } 

但要注意的是存儲在A.指針B :: b。如果將來你就可以變化率B :: B ,說重置它,指針可能會不正確。

如果你的編譯器支持靜態局部變量初始化部分中的C++ 11標準(就像@Mikhail注意到的那樣),你可以避免這些鎖定。

(BTW:什麼是這些類的目的沒有公共的方法呢?)。

+3

這個鎖什麼都不做,因爲它沒有保護從併發訪問到'A'。兩個線程同時獲得'A&'是安全的。自C++ 11以來,靜態局部變量也是線程安全的。 – Mikhail

相關問題