2016-03-05 23 views
0

我得到奇怪的行爲從C++構造函數,並需要澄清請。最近,我想利用Singleton模式。在線搜索示例並修改代碼以滿足需要後,我遇到了意外的行爲。只需在main()開始之前調用構造函數。爲了節省你的時間,通過代碼,這是4班。我只需要main.cpp,First.cpp,Second.cpp,Third.cpp和Singleton.cpp。C++全局對象構造函數與Vs.主要調用序列

在main.cpp中

int main() 
{ 
    cout << "Inside main()" << endl; 
    cout<<"val = "<<Singleton::Instance()->callThem()<<endl; 
    delete Singleton::Instance(); 
    return 0; 
} 

呼叫的順序是: 主() - >的Singleton :: callThem() - >首先:: callFirst() - >第二:: callSecond() - >第三:: callThird()

Singleton.cpp

#include "singleton.h" 
#include <iostream> 

First first; //source of the problem 

Singleton::Singleton() 
{ 
    std::cout<<"Singleton Constructor"<<std::endl; 
} 

Singleton::~Singleton() 
{ 
    std::cout<<"Singleton Destructor"<<std::endl; 
} 

Singleton* Singleton::m_pInstance = NULL; 

Singleton* Singleton::Instance() 
{ 
    if (!m_pInstance) 
    { 
     m_pInstance = new Singleton; 
    } 
    return m_pInstance; 
} 

    int Singleton::callThem() 
{ 
    return first.callFirst(); 
} 

輸出如下:

Third Constructor 
Second Constructor 
First Constructor 
Inside main() 
Third Constructor 
Second Constructor 
First Constructor 
Singleton Constructor 
val = 3 
Singleton Destructor 
First Destructor 
Second Destructor 
Third Constructor 
First Destructor 
Second Destructor 
Third Constructor 

Inside main()之前如何調用構造函數?不是主要()執行開始?

如果我刪除First first; //source of the problem,打印出的第一行是Inside main(),沒有在main()之前調用的構造函數。希望你的澄清。

+0

[C++:何時(以及如何)調用C++全局靜態構造函數?](http://stackoverflow.com/questions/1271248/c-when-and-how-are-c-global-static -constructors-called) –

+0

據我的經驗,全球ctors的序列無法控制,可以從一個構建變爲另一個構建,這會嚴重影響您的測試......您如何確認您已經測試過交付給您的客戶的順序?我一起工作的一個團隊完全不允許這個挑戰。 –

回答

0

Globals 在運行main()之前構建並初始化。

如果你正在尋找一個單例模式,我建議只使用:

template <typename T> 
class Singleton { 
    public: 
    static T *GetInstance() { 
      static T value; 
      return &value; 
    }; 
}; 

int main() { 
    int *x = Singleton<int>::GetInstance(); 
} 
0

不,前main [或至少,之前主要執行代碼的全局對象構造 - 有編譯器會在程序員提供的第一個代碼之前插入一個「初始化全局對象」的調用,但是現在大多數編譯器都是通過編譯器/鏈接器構建的「前主」函數來實現這一點。

另請注意,不同翻譯單元的全局構造函數之間的順序是完全未定義的 - 順序是在聲明順序的特定翻譯單元中定義的。

這是一個真正的麻煩,但它也是一個非常難的問題,以更好的方式解決。最好的解決方案是在你需要的時候構建對象,而不是使用全局對象 - 即使這也可能有點棘手。

有可能使Singleton回報shared_ptr可以解決這個問題 - 我已經使用類似的東西,以保持一個鎖活着,在使用該鎖的每個地方都有共享指針的拷貝,因此只有當鎖的最後一個用戶不見了,鎖自身被刪除。這個五行變更的解釋是爲什麼這是必要的,以及幾乎一樣長的提交信息,因爲這是棘手的問題,很容易被某人想到「啊,但我們可以刪除這些東西」。 [不是說shared_ptr是棘手的,但使用shared_ptr,而不是一個單一的全局變量IS]

0

希望你的澄清。

一個簡單易懂的方法來控制你認爲你可能希望有全局訪問可能是對象的initializaton(構造函數)序列...

一個。從

T1 theT1; // a global instance, with no control of initialization sequence 

替換 'T級' 的任何全局實例

T1* theT1 = nullptr; // a global instance ptr, constructed when you want. 

重複每一個全局對象。

b。顯式初始化main()之後的句柄,可能在main()的早期階段,但肯定是在需要對象之前。


請注意,有很多關於在多線程中創建單例的技術文獻。單身書的版本不是線程安全的。 (我認爲作者有一句話表示圖案書中的圖案都不是線程安全的。)

明確控制ctor序列極大地增加了您測試所裝運產品的信心。

相關問題