可复制类有默认构造函数就能保证:如果一个具体类是可复制的,它也就满足其他的“半正则”条件。
很多语言和库工具依赖默认构造函数初始化其元素。如果类是可复制的,默认构造函数经常能把定义移动状态的任务进行简化。
只在用户自定义的构造函数不存在时,编译器才会自动生成一个默认构造函数。所以以上代码中, vector vd1 是无法初始化的,因为 Date 中已经定义了一个构造函数,编译器就不会生成默认构造函数。没有默认构造函数代码写起来容易变得复杂。如果可以,尽量保持默认构造函数。
对于日期类来说,定义一个顺其自然的默认日期比较困难。宇宙大爆炸对于大部分人来说太久远了。这就好像把浮点数设置成 NaN 一样。
不过,大部分的日期类都有某个“起始日期”。比如最流行的 1970年1月1日。所以把这个日期作为默认日期就很容易了。
一个类里所有的成员都有默认构造函数,这个类也隐式地获得了一个构造函数。
注意,内置类型没有默认构造函数,其初始值不一定有用。
以上代码中,x.s 初始化为空 string。而 x.i 则是未初始化的一个数值。
静态分配的内置类型对象的陌生人值是 0,而局部的内置变量则不初始化。注意,你的编译器可能会给局部内置变量设定一个初始值。但是当你进行优化编译的时候,就不设置了。所以,以上代码看起来可以工作,但是是基于不可靠的未定义行为。假设你需要进行初始化,那么请明确定义初始化过程。
没有合理的默认构造函数的类,通常也不能复制,因此,这些类不在本指南建议范围内。
比如,一个基类如果不能复制的话,那么就不需要一个默认构造函数。
一个类如果在构建的过程中,需要接受一个调用者提供的资源的话,一般不能有默认构造函数。但是这种类,不在本指南建议范围,因为这些类通常不可复制。
一个类如果有某个“特殊状态”,就必须单独由某个成员函数,或额外过程来处理状态变化。不管是否能复制,这种类型很自然的会用某个特殊状态作为默认构造值。
类似的,特殊状态类型是可复制的。比如可复制的智能指针就有个特殊状态 “==nullptr”,必须用这个特殊状态作为其默认构造值。