条款04重难点

关于内置类型和STL的初始化就不多说了,下面主要来说下本节我认为的重点以及难点,对于难理解的部分,我尽量会试着实现来帮助理解。


重点1:自定义类的初始化

对于自定义类的初始化,很多人可能会混淆赋值和初始化。以下面的类为例:

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;
}

C++规定对象的成员变量的初始化动作发生在进入构造函数本体之前。上面的构造函数中,各成员变量(除numTimesConsulted)都不是被初始化,而是被赋值。numTimesConsulted是内置类型,不保证在赋值动作之前获得初值。

一般成员变量的初始化用初始化成员列表来实现:

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

这个构造函数和上一个结果相同,但效率较高。注意:如果成员变量是const或references,他们就一定需要初值,而不能被赋值。

还有一个问题注意下,当使用初始化列表时,初始化变量的顺序与列表的排列顺序没有关系,值取决于声明这些成员变量的顺序。


难点1:不同编译单元内定义之non-local static对象的初始化次序 (什么鬼啊???我想静静!!!)

static是静态的意思,表示这个变量不由栈分配,而存储在特有的全局变量/静态变量区域,具有长寿命的特点(从被构造出来,知道程序结束,才会由系统释放资源)。程序结束时static对象自动销毁,即他们的析构函数会在main函数结束时被自动调用。


non-local说明这个对象是全局的,而不是函数内的静态变量,说明它的范围广。


编译单元:当一个c或cpp文件在编译时,预处理器首先递归包含头文件,形成一个含有所有信息的单个源文件,这个源文件就是一个编译单元。

比如在文件1中定义了

int a=1;
在文件2中又会去使用

extern int a;
int b=a*3;
可以看到文件2应该在文件1后执行,否则b得到的值将是垃圾值(事实上不会,因为a是内置类型,编译器会初始化为0,如果是自定义类型,则会出现b为垃圾值,为了简单说明,这用int代替)。但是C++对不同文件执行的相对次序没有明确定义,这样b的值为多少就不确定了。解决这个问题的办法是,不要让变量有全局作用域,将每个non-local static对象搬到自己的专属函数内(该对象在此函数内被声明为static),这些函数返回一个reference指向它所包含的对象。

可以在文件1中定义:

int& GetA()
{
          static int a = 1;
          return a;
}
在文件2中调用:

int b = GetA();

这样就能保证a的初始化在前了。
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值