1. 程式人生 > >C++中關於全域性物件的初始化順序

C++中關於全域性物件的初始化順序

在stackoverflow上看到下面這樣一個問題:

這個問題很簡單,意思就是兩個全域性不同類的instance,其中一個依賴另一個,怎麼確保他們的構造順序。也就是說O2依賴於o1,o2被例項化之前,我們要確保o1一定要被構造出來,或者說初始化。就上面來看,如果這樣兩個全域性變數o1和o2在同一個編譯單元,說白了就是在同一個cpp檔案裡,那麼編譯器會保證按照他們出現的順序初始化。但是如果這樣兩個全域性變數在不同的編譯單元呢,這時候情況比較複雜了,編譯器已經不能控制他們的構造順序了,我們需要自己想辦法確定他們的構造順序,因為編譯器不能定義不同編譯單元全域性變數的初始化順序。下面是我的sample code,

這兩個全域性變數分別在不同的編譯單元,請看程式碼:
//************Independent.h*************************

#ifndef INDEPENDENT_H

#define INDEPENDENT_H

class Independent

{

    public:

        Independent();

        virtual ~Independent();

    protected:

    private:

};

#endif // INDEPENDENT_H


//**********************Independent.cpp*******************************

#include "Independent.h"

#include <iostream>

using namespace std;

Independent::Independent()

{

    cout<<"Independent::Independent()."<<endl;

}

Independent::~Independent()

{

    cout<<"Independent::~Independent()."<<endl;

}

Independent o1;

//*********************Dependent.h*****************************

#ifndef DEPENDENT_H

#define DEPENDENT_H

#include "Independent.h"

class Dependent

{

    public:

        virtual ~Dependent();

        Dependent();

    protected:

    private:

};

#endif // DEPENDENT_H



//***********************Dependent.cpp*****************************************

#include "Dependent.h"

#include <iostream>

#include "Independent.h"

using namespace std;

Dependent::Dependent()

{

    cout<<"Dependent::Dependent()."<<endl;

}

Dependent::~Dependent()

{

    cout<<"Dependent::~Dependent()."<<endl;

}

Dependent o2;



//***********************************main.cpp*********************************

int main()
{
    return 0;
}


程式的執行結果:

很明顯o2是在o1之前被構造出來的,這個應該是編譯器隨機選擇的,我們不能確定o2和o1他們兩個之間的構造順序。

下面是一些辦法,確定o1在o2之前一定被構造出來,因為在很多實際應用中,一些全域性物件依賴於另一些全域性物件的,雖然我們儘可能要少用全域性變數,不過今天討論的問題跟這個無關。請看修改過的程式碼:


點選(此處)摺疊或開啟

  1. //*************Independent.h********************
  2. #ifndef INDEPENDENT_H
  3. #define INDEPENDENT_H
  4. class Independent
  5. {
  6.     public:
  7.         Independent();
  8.         virtual ~Independent();
  9.     protected:
  10.     private:
  11. };
  12. #endif // INDEPENDENT_H


點選(此處)摺疊或開啟

  1. //*************Independent.cpp********************
  2. #include "Independent.h"
  3. #include <iostream>
  4. using namespace std;
  5. Independent::Independent()
  6. {
  7.     cout<<"Independent::Independent(), o1"<<endl;
  8. }
  9. Independent::~Independent()
  10. {
  11.     cout<<"Independent::~Independent()."<<endl;
  12. }
  13. const Independent *o1;


點選(此處)摺疊或開啟

  1. //*************dependent.h********************
  2. #ifndef DEPENDENT_H
  3. #define DEPENDENT_H
  4. #include "Independent.h"
  5. class Dependent
  6. {
  7.     public:
  8.         virtual ~Dependent();
  9.         Dependent(Independent* a);
  10.     protected:
  11.     private:
  12.         Dependent();
  13. };
  14. #endif // DEPENDENT_H


點選(此處)摺疊或開啟

  1. //*************Dependent.cpp********************
  2. #include "Dependent.h"
  3. #include <iostream>
  4. #include "Independent.h"
  5. using namespace std;
  6. extern Independent *o1;
  7. Dependent::Dependent()
  8. {
  9.     cout<<"Dependent::Dependent(), o2"<<endl;
  10. }
  11. Dependent::Dependent(Independent* a)
  12. {
  13.     if(a == NULL)
  14.         a = new Independent();
  15.     cout<<"Dependent::Dependent(Independent* a) o2"<<endl;
  16. }
  17. Dependent::~Dependent()
  18. {
  19.     cout<<"Dependent::~Dependent()."<<endl;
  20. }
  21. Dependent o2(o1);


點選(此處)摺疊或開啟

  1. //*************main.cpp********************
  2. #include <iostream>
  3. using namespace std;
  4. int main()
  5. {
  6.     return 0;
  7. }

下面是程式執行的結果:


很明顯,o2依賴於o1, 而o1也在o2之前被構造出來了。

總結:

1.我們要儘可能少用全域性變數

2.可以將一個物件的建構函式作為另一個物件建構函式的引數來保證他們的構造順序


閱讀(1586) | 評論(1) | 轉發(3) | 給主人留下些什麼吧!~~ 11_avatar_small.jpg

2013-09-16 23:40:12

貌似effectivec++裡有更好的辦法你可以看一下

回覆 | 舉報 評論熱議