条款4:非必要不提供 default constructor

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Sea_muxixi/article/details/84539037

1. 有些类的数据成员的值是必要的,因而在创建时就应该提供其值,其中的一个强制实现的方法就是不提供默认构造函数,如果不这么做的话,在使用对象的时候就要检验那个数据成员是否被正确赋值。

2. 如果为了强制某些数据成员在创建对象时就被赋值而不提供默认构造函数,那么在创建该对象的数组时就会遭遇因为没有默认构造函数而无法创建的情况,主要的解决方法有以下三种:

    1)在中创建数组并使用显示初始化列表。如 A a[5]={A(1),A(2),A(3),A(4),A(5)};

       缺点:1比较麻烦,如果有数组大小为1000,那么初始化列表就要有写1000个构造函数,显然不可能;

                  2只适用于堆栈数组

    2)使用指针数组(指针不受构造函数的束缚)。如 A* ptr_A[10];

       缺点:1如果指针指向的是中内存,则要记得delete否则会造成内存泄露(加重了程序员负担);

                  2存放指针数组需要额外空间

    3)使用内存池:使用operator new[] 函数预先申请一块内存,要使用的时候再使用placement new(定位new)依次构造,如:

void* rawMemory=operator new[](10*sizeof(A));

A *a=static_cast<A>(rawMemory);

for(int cou=0;cou<10;++cou)
    
    new (a+i) A(1);

      优点:可以在堆中创建数组而且不需占用额外空间

       缺点:1在数组内的对象结束生命时需要手动调用其析构函数,自然后调用operator delete[]释放内存

                  2如果采用一般的数组删除语法,结果将不可预期,因为删除一个不以new operator 获得的指针,结果没有定义。

                  3关于new operator和placement new 以及operator new的区别见条款8.

3. 如果该类没有默认构造函数,那么它有可能不适用有些模板,当然这里的“有些模板"主要指程序员自己定义的模板,对于标准库中的容器模板大多采用了2所述的内存池的方法,这也是使用某个类实例化标准库容器的必要条件只是该类能被复制而并不要求该类有默认构造函数的原因。也就是说,如果类的设计者自定义的类模板(准确的说应该是容器模板)使用内存池的方法的话,这一个缺陷可以避免。

4. 既然"缺乏 默认构造函数"会带来很多束缚,所以有人提出类应该提供默认构造函数,即使其没有足够的信息将对象初始化。

class EquipmentPiece
{
public:
	EquipmentPiece(int IDNumber = UNSPECIFIED);
private:
	static const int UNSPECIFIED;//一个魔术数字,意味没有被指定ID值
};

像上面这种添加无意义的默认构造函数,可能会影响程序效率。比如,程序函数需要测试这个字段是否真的初始化了,这会为测试行为付出时间代价,也会为测试代码付出空间代价。如果类构造函数可以确保对象的所有字段都会被正确初始化,上面的成本便可以免除。

总结:所以若默认构造函数无法提供这种保证,最好避免让默认构造函数出现

  

猜你喜欢

转载自blog.csdn.net/Sea_muxixi/article/details/84539037