静态初始化的相依性问题

静态初始化的相依性问题

1、在指定的翻译单元中,静态对象的初始化顺序严格按照对象在单元中定义出现的顺序,而清除顺序与初始化顺序相反。有时,作用域为多个翻译单元的静态对象,顺序上会有一些问题。如下例子:

//: C10:Out.cpp {O}

// First file

#include <fstream>

std::ofstream out("out.txt"); ///:~

//: C10:Oof.cpp

// Second file

//{L} Out

#include <fstream>

extern std::ofstream out;

class Oof {

public:

  Oof() { std::out << "ouch"; }

} oof;

int main() {} ///:~

如要先执行的是第二个文件,可此时out还没有建立,便引起混乱。再如:

第一个文件中:

extern int y;

int x = y + 1;

and in a second file you have at the global scope:

extern int x;

int y = x + 1;

如果两个文件的执行顺序不一样,x和y则是两个不同的结果。

有三种方法来处理:避免相互依赖;或尽量定义静态对象于一个文件中。如果实在不行,用如下两个方法。

2、两种解决方法

法一:在库头文件中加一个额外的类,这个类负责库的静态对象的初始化。

#include <iostream>

using namespace std;

//: C10:Initializer.h

// Static initialization technique

#ifndef INITIALIZER_H

#define INITIALIZER_H

#include <iostream>

extern int x; // Declarations, not definitions

extern int y;

class Initializer {

static int initCount;

public:

  Initializer() {

std::cout << "Initializer()" << std::endl;

// Initialize first time only

if(initCount++ == 0) {

  std::cout << "performing initialization"

<< std::endl;

  x = 100;

  y = 200;

}

  }

  ~Initializer() {

std::cout << "~Initializer()" << std::endl;

// Clean up last time only

if(--initCount == 0) {

  std::cout << "performing cleanup" 

<< std::endl;

  // Any necessary cleanup here

}

  }

};

// The following creates one object in each

// file where Initializer.h is included, but that

// object is only visible within that file:

static Initializer init;

#endif // INITIALIZER_H ///:~

 //: C10:InitializerDefs.cpp {O}

// Definitions for Initializer.h

#include "Initializer.h"

// Static initialization will force

// all these values to zero:

int x;

int y;

int Initializer::initCount;

///:~ 

 //: C10:Initializer.cpp {O}

// Static initialization

#include "Initializer.h"

///:~

//: C10:Initializer2.cpp

//{L} InitializerDefs Initializer

// Static initialization

#include "Initializer.h"

using namespace std;

int main() {

  cout << "inside main()" << endl;

  cout << "leaving main()" << endl;

} ///:~

注意:在任何动态初始化进行前,静态存储区已被设置成0。

This example used built-in types as the global static objects. The technique also works with

 classes, but those objects must then be dynamically initialized by the Initializer class. 

One way to do this is to create the classes without constructors and destructors, but instead

 with initialization and cleanup member functions using different names. A more common 

approach, however, is to have pointers to objects and to create them using new inside

 Initializer( ).

法二:对于任何初始化依赖因素来说,可以把一个静态对象放在一个能返回对象引用的函数中,使用这种方法,访问静态对象的惟一途径就是调用这个函数。函数第一次调用时,强迫初始化发生。

//: C10:Dependency1.h

#ifndef DEPENDENCY1_H

#define DEPENDENCY1_H

#include <iostream>

class Dependency1 {

  bool init;

public:

  Dependency1() : init(true) {

std::cout << "Dependency1 construction" 

  << std::endl;

  }

  void print() const {

std::cout << "Dependency1 init: " 

  << init << std::endl;

  }

};

#endif // DEPENDENCY1_H ///:~

//: C10:Dependency2.h

#ifndef DEPENDENCY2_H

#define DEPENDENCY2_H

#include "Dependency1.h"

class Dependency2 {

  Dependency1 d1;

public:

  Dependency2(const Dependency1& dep1): d1(dep1){

std::cout << "Dependency2 construction ";

print();

  }

  void print() const { d1.print(); }

};

#endif // DEPENDENCY2_H ///:~

第二个类初始化由第一个类的对象完成,将导致相互依赖。

//: C10:Technique2.cpp

#include "Dependency2.h"

using namespace std;

// Returns a value so it can be called as

// a global initializer:

int separator() {

  cout << "---------------------" << endl;

  return 1;

}

注意:不能全局都调用一个函数,除非该函数用来执行一个变量的初始化操作。

// Simulate the dependency problem:

extern Dependency1 dep1;

Dependency2 dep2(dep1);

Dependency1 dep1;

int x1 = separator();

// But if it happens in this order it works OK:

Dependency1 dep1b;

Dependency2 dep2b(dep1b);

int x2 = separator();

// Wrapping static objects in functions succeeds

Dependency1& d1() {

  static Dependency1 dep1;

  return dep1;

}

Dependency2& d2() {

  static Dependency2 dep2(d1());

  return dep2;

}

//现在访问这些静态对象的唯一方法就是调用这两个函数,并在函数第一次调用时,强迫初始化发生

int main() {

  Dependency2& dep2 = d2();

} ///:~

下面应用这个技术,实现一个例子:

//: C10:Dependency1.h

#ifndef DEPENDENCY1_H

#define DEPENDENCY1_H

#include <iostream>

class Dependency1 {

  bool init;

public:

  Dependency1() : init(true) {

std::cout << "Dependency1 construction" 

  << std::endl;

  }

  void print() const {

std::cout << "Dependency1 init: " 

  << init << std::endl;

  }

};

#endif // DEPENDENCY1_H ///:~

//: C10:Dependency2.h

#ifndef DEPENDENCY2_H

#define DEPENDENCY2_H

//#include "Dependency1.h"

class Dependency2 {

  Dependency1 d1;

public:

  Dependency2(const Dependency1& dep1): d1(dep1){

std::cout << "Dependency2 construction ";

print();

  }

  void print() const { d1.print(); }

};

#endif // DEPENDENCY2_H ///:~

//: C10:Dependency1StatFun.h

#ifndef DEPENDENCY1STATFUN_H

#define DEPENDENCY1STATFUN_H

//#include "Dependency1.h"

extern Dependency1& d1();

#endif // DEPENDENCY1STATFUN_H ///:~

 //: C10:Dependency2StatFun.h

#ifndef DEPENDENCY2STATFUN_H

#define DEPENDENCY2STATFUN_H

//#include "Dependency2.h"

extern Dependency2& d2();

#endif // DEPENDENCY2STATFUN_H ///:~

//: C10:Dependency1StatFun.cpp {O}

//#include "Dependency1StatFun.h"

Dependency1& d1() {

  static Dependency1 dep1;

  return dep1;

} ///:~

//: C10:Dependency2StatFun.cpp {O}

//#include "Dependency1StatFun.h"

//#include "Dependency2StatFun.h"

Dependency2& d2() {

  static Dependency2 dep2(d1());

  return dep2;

} ///:~

 //: C10:Technique2b.cpp

//{L} Dependency1StatFun Dependency2StatFun

//#include "Dependency2StatFun.h"

int main() { d2(); } ///:~

    必须保证每一个定义了静态对象的函数只有一个定义,故不能把定义了静态对象的函数作为内联函数。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值