构造函数
构造函数包括默认构造函数、拷贝构造函数和一般构造函数。
在编程时,如果程序员不显式声明和定义上述函数,编译器将自动产生4个public inline的默认函数。
- A(); // 默认构造函数
- A(const A&); // 拷贝构造函数
- A& operator=(const A& a) // 拷贝构造函数
- ~A(); // 默认析构函数
默认构造函数
当一个类没有定义构造函数时,编译器才生成默认构造函数。
当定义类对象没有提供初始化式时,使用默认构造函数进行初始化。
没有默认构造函数的类的局限
- 具有该类类型成员的类,必须通过构造函数初始化列表进行初始化。
- 该类不能用作动态分配数组(new)的元素类型。
- 使用该类作为元素类型的静态数组,必须显式初始化。
- 不适用于没有提供初始化的容器
默认构造函数的使用
- A test(); ×
- A test; √
- A test = A(); √
拷贝构造函数
对于一个类X,如果一个构造函数的第一个参数是下列之一:
- X&
- const X&
- volatile X&
- const volatile X&
且没有其他参数或其他参数都有默认值,那么这个函数是拷贝构造函数。
拷贝构造函数不能由成员函数模版生成.
何时发生拷贝
- 手动调用
- 函数返回类对象
- 函数有类类型参数
- 容器初始化
隐患
- 当类有指针类型的成员时,简单拷贝(浅拷贝)将造成两个不同对象的指针指向同一区域,出现访问冲突、多次delete等错误。
- 大量拷贝构造函数的调用,降低运行效率。
解决
- 显式定义拷贝构造函数(为指针重新申请内存,并拷贝内存数据 -- 深拷贝)
- 禁止拷贝(通过成员函数进行赋值,提高运行效率)
如何禁止拷贝
1 class Widget 2 { 3 ... 4 private: 5 Widget(const Widget&); // 声明为私有 6 Widget& operator=(const Widget&); 7 }