• 条款47: 确保非局部静态对象在使用前被初始化


    class FileSystem { ... };            // 这个类在你
                                         // 的程序库中
    
    FileSystem theFileSystem;            // 程序库用户
                                         // 和这个对象交互
    //////////////////////////////////////////////////////////
    class Directory {                    // 由程序库的用户创建
    public:
      Directory();
      ...
    };
    
    Directory::Directory()
    {
      通过调用theFileSystem的成员函数
      创建一个Directory对象;
    }

    Directory tempDir;                  // 临时文件目录

    现在,初始化顺序的问题变得很明显了:除非theFileSystem在tempDir之前被初始化,否则,tempDir的构造函数将会去使用还没被初始化的theFileSystem。但theFileSystem和tempDir是由不同的人在不同的时间、不同的文件中创建的。怎么可以确认theFileSystem在tempDir之前被创建呢?


    在某个特定的编译单元(即,源文件)中,构造函数可以确保对象在创建时被初始化;但如果在某个编译单元中,一个对象的初始化要依赖于另一个编译单元中的另一个对象的值,并且这第二个对象本身也需要初始化,事情就会变得更复杂。

    非局部静态对象指的是这样的对象:

    · 定义在全局或名字空间范围内
    · 在一个类中被声明为static,或
    · 在一个文件范围被定义为static。

    局部静态对象:函数内的static对象

    对于不同被编译单元中的非局部静态对象,你一定不希望自己的程序行为依赖于它们的初始化顺序,因为你无法控制这种顺序。即:你绝对无法控制不同编译单元中非局部静态对象的初始化顺序

    解决方案:首先,把每个非局部静态对象转移到函数中,声明它为static。其次,让函数返回这个对象的引用。这样,用户将通过函数调用来指明对象。换句话说,用函数内部的static对象取代了非局部静态对象

    虽然关于 "非局部" 静态对象什么时候被初始化,C++几乎没有做过说明;但对于函数中的静态对象(即,"局部" 静态对象)什么时候被初始化,C++却明确指出:它们在函数调用过程中初次碰到对象的定义时被初始化。所以,如果你不对非局部静态对象直接访问,而用返回局部静态对象引用的函数调用来代替,就能保证从函数得到的引用指向的是被初始化了的对象。这样做的另一个好处是,如果这个模拟非局部静态对象的函数从没有被调用,也就永远不会带来对象构造和销毁的开销;而对于非局部静态对象来说就没有这样的好事。

    class FileSystem { ... };            // 同前
    FileSystem& theFileSystem()          // 这个函数代替了
    {                                    // theFileSystem对象
    
      static FileSystem tfs;             // 定义和初始化
                                         // 局部静态对象
                                         // (tfs = "the file system")
    
      return tfs;                        // 返回它的引用
    }
    
    class Directory { ... };             // 同前
    
    Directory::Directory()
    {
      同前,除了theFileSystem被
      theFileSystem()代替;
    }
    
    Directory& tempDir()                 // 这个函数代替了
    {                                    // tempDir对象
    
      static Directory td;               // 定义和初始化
                                         // 局部静态对象
    
      return td;                         // 返回它的引用
    }

     以上方法常用于单例模式的实现


    有两个全局对象,我们知道,放在同一个CPP中时会按序初始化(编译器按序生成构造函数调用),如果这两个全局对象在不同的CPP中,有没有方法能控制其构造函数调用次序呢?(链接问题)

    全局对象的初始化次序在C++标准中没有定义。
    可以这样做:
    假设你需要一个类A的对象a,这么写(使用局部静态对象,返回它的引用)
    A& getA()
    {
      static A a;
      return a;
    };
    这样能够保证使用a的时候a已经被初始化了。

    参考:

    http://bbs.csdn.net/topics/30293003

  • 相关阅读:
    MySQL的max()函数使用时遇到的小问题
    scp命令需要指定端口时要紧跟在scp后
    linux系统之间基于密钥对免输入密码登陆
    c++的引用用法
    预测模型
    mysql出现ERROR 1366 (HY000):的解决办法
    R语言可视化--颜色
    R语言可视化--ggplot函数
    R语言可视化--qplot函数
    R语言可视化二
  • 原文地址:https://www.cnblogs.com/ljygoodgoodstudydaydayup/p/3934741.html
Copyright © 2020-2023  润新知