【C++ Basics】非必要不提供default constructor

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

该方法的两个缺点:

  1. 必须记得将数组所指的所有对象删除,如果忘了就会出现资源泄露问题;
  2. 需要的内存总量比较大,因为需要一些空间来放置指针,还需要一些空间放置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 出现。
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值