现在的位置: 首页 > 综合 > 正文

effective C++ 条款 4:确定对象被使用前已先被初始化

2012年02月28日 ⁄ 综合 ⁄ 共 1846字 ⁄ 字号 评论关闭

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

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)。

抱歉!评论已关闭.