C++中关于全局对象的初始化顺序

1690阅读 0评论2013-10-26 helianthus_lu
分类: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

using namespace std;

 

Independent::Independent()

{

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

}

Independent::~Independent()

{

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

}

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

#include "Independent.h"

 

using namespace std;

 

 

Dependent::Dependent()

{

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

}

 

Dependent::~Dependent()

{

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

}

 

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.可以将一个对象的构造函数作为另一个对象构造函数的参数来保证他们的构造顺序


上一篇:Linux中的内存管理
下一篇:【转载】软件开发启示录——迟到的领悟