default constructor
在没有外来信息的情况下,为对象进行默认初始化。
- eg. 数值对象可以被初始化为0或者一个无意义值;指针可能被初始化为NULL,或者无意义值;数据结构如link lists,hash tables,maps等,可被初始化为空容器;
- 但是对于某些类的对象进行默认初始化,产生出来的对象将毫无意义。
缺乏default constructor,其运行时可能在3种情况下出现问题:
1. 产生数组时
没有任何办法可以为数组中的对象指定 constructor 自变量。
class EquipmentPiece {
public:
EquipmentPiece(int IDNumber);
...
};
//1. 产生数组时
EquipmentPiece pieces[10];
// 错误!无法调用 EquipmentPiece ctors
EquipmentPiece *pieces = new EquipmentPiece[10];
// 错误!另有一些问题
解决方法1:使用 non-heap 数组
注意:此法无法延伸至 heap 数组
int ID1, ID2, ID3, ..., ID10; // 变量
...
EquipmentPiece pieces[] = {
EquipmentPiece(ID1),
EquipmentPiece(ID2),
EquipmentPiece(ID3),
...,
EquipmentPiece(ID10),
}
解决方法2:使用“指针数组”而非“对象数组”
typedef EquipmentPiece* PEP;
// PEP 是个指向 EquipmentPiece 的指针
PEP piece[10]; // 需要调用 ctor
PEP *pieces = new PEP[10];
// 数组中的各指针可用来指向不同的 EquipmentPiece对象
for (int i = 0; i < 10; ++i) {
piece[10] = new EquipmentPiece(ID Number);
}
该方法的两个缺点:
- 必须记得将数组所指的所有对象删除,如果忘了就会出现资源泄露问题;
- 需要的内存总量比较大,因为需要一些空间来放置指针,还需要一些空间放置EquipmentPiece对象。
//分配足够的raw memory
void *rawMemory =
operator new[](10*sizeof(EquipmentPiece));
//让pieces指向此块内存,当做1个EquipmentPiece数组
EquipmentPiece *pieces =
static_cast<EquipmentPiece*>(rawMemory);
//利用“placement new”构造这块内存中的EquipmentPiece对象
for(int i = 0; i < 10; ++i) {
new (&pieces[i]) EquipmentPiece(ID Number);
}
过度使用内存这个问题可以避免,方法:
- 先为数组分配 raw memory,然后使用 placement new 在这块内存上构造EquipmentPiece对象;
- 还是必须提供给 constructor一个自变量作为每EquipmentPiece object 的初值(这项技术允许在缺乏“default constructor”的情况下仍然能产生对象数组,并不意味着可以回避提供 constructor 自变量);
placement new 必须手动调用 destructors,以及调用 operator delete[ ]释放raw memory:
//以构造顺序的相反顺序析构
for(int i = 9; i >= 0; --i) {
pieces[i].~EquipmentPiece();
}
//释放raw memory
operator delete[](rawMemory);
2. 不适用于 template-based container classes
对于 templates 而言,被实例化的“目标类型”必须得有1个defatut constructorus。
template<class T>
class Array {
public:
Array(int size);
...
private:
T *data;
}
template<class T>
Array<T>::Array(int size)
{
data = new T(size); // 数组中的而每个元素都调用T::T()
...
}
3. 虚基函数(virtual base classes)的要求
- Virtual base classes如果缺乏default constructors,则 Virtual base classes constructors的自变量必须由欲产生的对象的派生层次最深的class 提供;
- 一个缺乏 default constructors 的 virtual base class,要求其所有的 derived classes——不论距离多远——都必须知道且了解其意义,并提供 virtual base class的constructors自变量。
总结
添加毫无意义的 defatult constructor ,会影响 classes 的效率。
- 如果 class constructors 可以确保对象所有字段都会被正确初始化,即可以免除为测试行为付出的时间代价、为测试代码付出的空间代价,因为其可执行文件和程序库都变大了。
- 如果无法保证,最好避免 default constructor 出现。