C++中成员变量的初始化操作(4)---《Effective C++》

来源:互联网 发布:营销活动数据库设计 编辑:程序博客网 时间:2024/06/05 08:49

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

C++类中的成员变量,我们一般都是对其进行赋值操作,如:

class ABEntry{public:    ABEntry(const std::string&name,const std::string& address,const std::list<PhoneNumber>& phones);private:    std::string theName;    std::string theAddress;    std::list<PhoneNumber> thePhones;    int numTimeConsulted;};ABEntry::ABEntry(const std::string& name,const std::string& address,const std::list<PhoneNumber>& phones){    theName=name;    theAddress=address;    thePhones=phones;    numTimeConsulted=0;}

上面的这种操作都是赋值操作,而非初始化操作,初始化发生的时间更早,发生于这些成员的default构造函数被自动调用之时,比进入构造函数本体的时间更早一些,相当于先执行了初始化操作,然后执行了复制操作,效率较低。
我们怎样解决这种问题呢?直接对其执行初始化操作,提高效率,有一种优化的方法称之为成员初始列的替换赋值动作,如

ABEntry::ABEntry(const std::string& name,const std::string& address,const std::list<PhoneNumber>& phones):theName(names),theAddress(address),thePhones(phones),numTimesConsulted(0){}

这中操作成为成员初始列方法,都是初始化操作,构造函数本体不必有任何动作,theName以name为初值进行copy构造,以此类推。

C++中对于成员的初始化顺序要求尤其严格,static变量在类内部申明,在类外部定义,同时如果想要修改static成员变量的值,只能通过在调用类中定义的static成员函数进行修改。

#include <iostream>#include <cstring>using namespace std;class TextBlock{public:    TextBlock(string s){        this->text = s;    }    const char& operator[](std::size_t position)const{        cout << "我为const代言" << endl;        return text[position];    }    char& operator[](std::size_t position){        cout << "我为non-const代言" << endl;        return text[position];    }    static int i;    static int changeStatic(int &i){        i = 100;        return i;    }private:    std::string text;};int TextBlock::i = 10;TextBlock::i = 1000;

如果我们这样进行强制修改的话会出错提示,没有存储类或者类型说明符。
对于C++中的non-local static成员变量,解释一下,non-local static成员变量包括global对象,namespace作用域,class内,file作用域中所有被申明为static的对象,而local static成员变量指的是在函数中定义的static成员变量,由于non-local static成员变量的初始化顺序可能存在依赖关系,而这种依赖关系不一定被满足,如下面代码所示:

class FileSystem{public:    ...    std::size_t numDisks() const;    ...}extern FileSystem tfs;class Directory{public:    Directory(params);    ...}Directory::Directory(params){    ...    std::size_t disks=tfs.numDisks();//使用tfs对象    ...}Directory tempDir(params);

可以看出tfs必须在tempDir之前仙贝初始化,否则tempDir的构造函数会用到尚未被初始化的tfs。
因此我们需要一种方法进行解决这种问题,方法是:将每个non-local static对象搬到自己的专属函数内,该对象在此函数中被申明为static,这些函数返回一个reference指向它所含的对象,修改办法如下:

class FileSystem{...}FileSystem& tfs(){    static FileSystem fs;    return fs;}class Directory{...}Directory::Directory(params){    ...    std::size_t disks=tfs().numDisk();    ...}Directory& tempDir(){    static Directory td;    return td;}

这样可以保证在tfs在tempDir之前被初始化。

阅读全文
0 0
原创粉丝点击