我確實看到了(對我來說)奇怪的訪問衝突異常。我會盡量減少這個問題。我有一個A類和一個單身物體sing_。代碼看起來莫名其妙地像:在初始化程序列表中創建單例對象會導致訪問衝突(僅限發佈模式)
class A {
A();
Sing& sing_;
}
A::A() : sing_(Sing::instance()){
call a method that creates a local copy of Singleton Sing.
....
}
類唱出單身繼承:
class Sing : public Singleton<Sing>{
friend class Singleton<Sing>;
....
}
辛格爾頓本身看起來像(這是在QuantLib庫的實現)
template <class T>
class Singleton : private boost::noncopyable {
public:
static T& instance();
protected:
Singleton() {}
};
template <class T>
T& Singleton<T>::instance() {
static std::map<Integer, boost::shared_ptr<T> > instances_;
#if defined(QL_ENABLE_SESSIONS)
Integer id = sessionId();
#else
Integer id = 0;
#endif
boost::shared_ptr<T>& instance = instances_[id];
if (!instance)
instance = boost::shared_ptr<T>(new T);
return *instance;
}
我的項目代碼嵌入在Qt Gui環境中。以調試模式啓動它不會引起麻煩。當我嘗試以發佈模式啓動時,情況發生可怕的變化。這是主要的方法:
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
GUI w;
w.show();
w.setup(argc, argv);
return a.exec();
}
最後類GUI看上去略像:
class GUI : public QMainWindow
{
Q_OBJECT
public:
GUI(QWidget *parent = 0, Qt::WFlags flags = 0);
~GUI();
private:
boost::shared_ptr<A> a_;
};
當我在Release模式下啓動該代碼會發生以下情況:
的方法稱爲___ tmainCRTstartup()被調用。其中調用_WinMain方法。
該方法內部WinMain(甚至在主方法被調用並且創建GUI對象 之前)A的構造函數被調用。這意味着成員唱歌將被初始化。
sing_在Sing :: instance()的調用過程中被初始化。一切看起來都很好。
A的構造函數被執行。其中有一個地方參考Sington創建的單體對象。在該行
boost::shared_ptr<T>& instance = instances_[id];
調用星::實例()導致訪問衝突當我看着instances_ [ID]在那個地方(調試在Release模式)地圖看起來相當銷燬。這意味着地圖中有一個元素。但關鍵不是0而是一個非常負的整數,而且這個值看起來很奇怪。
我絕對不知道這裏出了什麼問題。
在不斷變化的成員sing_是一個靜態成員解決了這個問題:
class A {
A();
static Sing& sing_;
}
Sing& sing_ = Sing::instance();
A::A() {
call a method that creates a local copy of Singleton Sing.
....
}
這當然不錯,但我真的不知道什麼是這兩種實現之間的「大」的區別。爲什麼第一種方式在訪問衝突中結束?任何暗示是讚賞。
OP Y U SINGLETONS? – 2013-03-08 16:53:08
單身並不是一個真正的邪惡,他們已經得到了他們的使用。 – 2013-03-08 16:57:56
當然'sessionId'返回一些垃圾? PS:迄今爲止我所見過的單反反模式最糟糕的濫用。 – 2013-03-08 17:01:11