zoukankan      html  css  js  c++  java
  • effective C++ 条款 4:确定对象被使用前已先被初始化

    对象的成员变量的初始化动作发生在进入构造函数本体之前

    ABEntry::ABEntry(const std::string& name, const std::list<PhoneNumber>& phones)

    {

        theName = name;                   //这些都是赋值,不是初始化

        thePhones = phones;

        numTimesConsulted = 0;

    }

    这个构造函数首先调用default构造函数为theName, thePhones设初值,然后立刻对他们赋予新值

    ABEntry::ABEntry(const std::string& name, const std::list<PhoneNumber>& phones)

    :theName(name),                             // 这些是初始化

    thePhone(phones),

    numTimesConsulted(0)

    {}

    本例中的构造函数分别以name等为初值进行copy构造。

    class的成员变量总是以其声明的次序被初始化。跟初始化列表中的顺序无关

    编译单元是指产出单一目标文件的那些源码。基本上是单一源码文件加上其所含的头文件。

    static对象,从被构造出来到程序结束为止,析构函数会在main()结束时被自动调用。

    函数内的static对象称为local static对象;其他的包括global对象,定义于namespace作用域内的对象,在class内、以及在file作用域内被声明为static的对象被称为non-local static对象。

    c++对“定义于不同编译单元内的non-local static对象”的始化次序并无明确定义

    class FileSystem{                  //来自你的程序库

    public:

        …

        std::size_t numDisk() const;

        …

    };

    extern FileSystem tfs;                 //预备给客户用的对象

    class Directory{                          //由程序库客户建立

    public:

        Directory(params);

        …

    };

    Directory::Directory(params)

    {

        …

        std::size_t disks = tfs.unmDisks();              //使用tfs对象

        …

    }

    Directory tempDir(params)

    由于tempDir和tfs属于定义在不同编译单元内的non-local static对象,不能保证tfs在tempDir之前被初始化。

    消除这个问题的方法是将每个non-local static对象搬到自己的专属函数内,换成local static对象,做法有点像Sigleton模式。

    c++保证函数内的local static 对象会在该函数被调用期间,首次遇上该对象的定义式时被初始化。所以以函数调用(返回一个reference指向local static对象)来替换直接访问non-local static对象。这样保证获得一个经过初始化的对象。并且,如果从未调用过non-local static对象的“仿真函数”,就绝不会引发构造函数和析构函数成本; 真正的non-local static对象可没这么便宜。

    //reference returning 函数防止初始化次序问题

    class FileSystem{…};

    FileSystem& tfs()      //这个函数用来替换tfs对象

    {

        static FileSystem fs;

        return fs;

    }

    class Directory{…};

    Directory::Driectory(params)

    {

        …

        std::size_t disks = tfs().numDisks();

        …

    }

    Directory& tempDir()      //这个函数用来替换tempDir对象

    {

        static Directory td;

        return td;

    }

    任何non-const static对象不论是local或non-local,在多线程环境下“等待某事发生”都会有麻烦。处理这个麻烦的一种做法是:在程序的单线程启动阶段手工调用所有reference-returning函数,这可消除与初始化有关的“竞速形势”(race condition)。

  • 相关阅读:
    Linux Bash
    grep 及正则表达式
    Linux 文件系统
    Linux 操作系统基础
    常见的磁盘I/O和网络I/O优化技巧
    NIO的工作方式
    网络I/O 工作机制
    spring Boot环境下dubbo+zookeeper的一个基础讲解与示例
    深入分析Java I/O 工作机制
    CDN工作机制和负载均衡
  • 原文地址:https://www.cnblogs.com/lidan/p/2315537.html
Copyright © 2011-2022 走看看