您的位置:首页 > 职场人生

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

2012-02-06 22:35 363 查看
读取未初始化的值会导致不明确的行为。

最佳处理办法是:永远在使用对象之前先将它初始化。对于无任何成员的内置类型,你必须手工初始化。

int x = 0;
const char * text = "A C-style string";
double d;
std::cin>>d;//以读取input stream的方式完成初始化

内置类型以为的任何类型,初始化责任落在构造函数身上。

规则很简单:确保每一个构造函数都将对象的每一个成员初始化。

“重要的是别混淆了赋值和初始化”??

using namespace std;

class PhoneNumber{...};
class ABEntry
{
public:
ABEntry(const string& name, const string& address,
const list<PhoneNumber>& phones);
private:
string theName;
string theAddress;
list<PhoneNumber> thePhones;
int numTimesConsulted;
};
ABEntry::ABEntry(const string& name, const string& address,
const list<PhoneNumber>& phones)
{
theName = name;//这些都是赋值而非初始化
theAddress = address;
thePhones = phones;
numTimesConsulted = 0;
}

ABEntry::ABEntry(const string& name, const string& address,
const list<PhoneNumber>& phones)
:theName(name),theAddress(address),thePhones(phones),numTimesConsulted(0)
{}//这些都是初始化

初始化的效率要高

有些情况下即使面对的成员变量属于内置类型也一定得使用初始值。如果成员变量是const或引用,它们就一定需要初值,不能被赋值,为了避免需要记住成员变量何时必须在成员初值列中初始化,何时不需要,最简单的做法就是:总是使用成员初值列

基类更早于继承类被初始化。

当你在成员初值列中条列各个成员时,最好总是以其声明次序为次序。

“不同编译单元内定义之non-loacl static对象的初始化次序”??

1.所谓static对象,其寿命从被构造出来直到程序结束为止,因此stack和heap-based对象都被排除,这种对象包括global对象,定义于namespace作用域内的对象,在classes内,在函数内,以及在file作用域内被声明为static的对象。

函数内的static对象被称为local static对象(因为他们对函数而言是local),其他static对象称为non-local static对象,程序结束时static对象会被自动销毁,也就是他们的析构函数会在main()结束时被自动调用。

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

//C++对“定义于不同编译单元内的non-loacl 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对象,用来存放临时文件
Directory tempDir(param);//为临时文件创建目录

/**
除非tfs在tempDir之前被初始化,否则tempDir的构造函数会用到尚未初始化的tfs,
但是不确定tfs会在tempDir之前被初始化。
*/

修改--->

将每个non-local static对象搬到自己的专属函数内(该对象在此函数内被声明为static)。这些函数返回一个引用指向它所含的对象。然后用户调用这些函数,而不是直接指涉这些对象。non-local static对象被loacl static对象替换了,这是Singleton模式的一个常见实现手法。

这个手法的基础在于:C++保证,函数内的local static对象会在“该函数被调用期间”“首次遇上该对象之定义式”时被初始化。所以如果你以“函数调用”(返回一个引用指向local static对象)替换“直接访问non-local static对象”,保证了你所获得的那个引用将指向一个历经初始化的对象。

class FileSystem{...};//同前
FileSystem& tfs()  //这个函数用来替换tfs对象;它在FileSystem class
{                 //中可能是个static
static FileSystem fs;//定义并初始化一个local static对象
return fs;    //返回一个引用指向上述对象
}
class Directory{...};
Directory::Directory(params)
{
std::size_t disks  = tfs().numDisks();
}

Directory& tempDir() //这个函数用来替换tempDi日对象;
{                    //它在Direcctory class中可能是个static
static Directory td; //定义并初始化loacl static对象
return td;      //返回一个引用指向上述对象
}


1.为内置对象进行手工初始化,因为C++不保证初始化它们。

2.构造函数最好使用成员初值列,而不是在构造函数本体内使用赋值操作,初值列列出的成员变量,其排列次序应该和它们在class中声明次序相同。

3.为免除“跨编译单元之初始化次序”问题,请以local static对象替换non-local static 对象。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  职场 初始化 休闲