且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

《C++编程惯用法——高级程序员常用方法和技巧》——2.9 静态对象的构造

更新时间:2022-09-18 21:41:45

本节书摘来自异步社区出版社《C++编程惯用法——高级程序员常用方法和技巧》一书中的第2章,第2.9节,作者: 【美】Robert B. Murray ,更多章节内容可以访问云栖社区“异步社区”公众号查看。

2.9 静态对象的构造

我们也可以用构造函数来对那些有着static存储类型的对象进行初始化:

static String hello("Hello world");

C++编译系统确保:所有的静态对象在它们被使用之前都会被初始化。很多的编译器实现的做法是将所有的静态对象放到main函数被调用之前进行初始化,但C++语言规则中也允许我们在(动态的)链接时期用动态的链接器来初始化编译单元中的所有对象。

对于在同一个编译单元中出现的静态对象,它们的初始化顺序和它们在代码中出现的顺序是一致的:

String dafault_name("foo");
  String default_src_file(default_name + ".c");

在上面的代码中,我们可以确保default_name的初始化操作要早于default_src_file的初始化操作。在同一文件中出现的静态对象,它们的析构顺序和它们的构造顺序正好相反,因此default_src_file必须早于default_name被析构。

在不同文件中的初始化操作的顺序则是未定义的:

extern String default_name;
String default_src_file(default_name +".c");  //Bug!

我们无法保证,default_name会早于default_src_file被创建。

对于上面的那个问题,我们并没有一个简单的解决方法。如果我们有着一个依赖于定义在其他文件中的其他静态对象的静态对象(如default_src_file),我们就应该试着将这两个对象放在同一个文件中(这样我们就可以得到它们的初始化的确切顺序)。如果我们做不到这点,我们就不得不将这些初始化操作延迟到main函数被执行时才执行它们:

extern String default_name;
String* default_src_file = 0;

Static void
init_names(){
   default_src_file = new String (default_name + ".c");
   //其他的初始化操作
}

main() {
   init_names();

如果我们的代码来自于一个函数库,在那里并没有我们所期望的main函数,那么我们还可以在每个使用了具有依赖关系的静态对象的函数中对该对象进行检测,看看它是否已经被初始化了:

extern String default_name;
String* default_src_fi1e = 0;

void
routine_that_uses_name(){
  if (default_src_file == 0)
     default_src_file = new String(default_name + ".C");
  //使用default_src_file
我```