C++构造函数分两种:普通构造函数和复制构造函数。其中复制构造函数的参数为自身类型的常引用,即const 类名 &修饰。为什么要传个常引用呢?因为是引用,所以对引用的操作会影响到原来的对象。为了防止复制构造函数里对引用的修改,所以加上const去修饰,const修饰的对象是不能被修改的,包括它的任何成员。

构造函数调用

class Student
{
	public:
		int a;
		Student(int arg){
			this->a = arg;
		}
		Student(const Student & stu){
		
		}
};

以下是两种构造函数的调用与其等价的调用形式

Student stu1 = 18; // 等价于Student stu1(18)
Student stu2 = stu1; // 等价于Student stu2(stu1)

初始式

我们可以使用初始式来初始化类的成员变量。在构造函数后跟上":"号,后面再跟上成员变量名,变量名后用()来初始化,把构造函数里的参数传到变量名后的括号里,就可以对相应的变量进行初始化。这不影响构造函数的调用方式。

class Teacher {
public:
    int id = 0;
    Teacher(int a):id(a){

    }

};

构造函数调用:

Teacher teacher1 = 12345;
Teacher teacher2(12345);

浅复制与深复制

浅复制是很容易导致程序运行错误,这是初学者常犯的错误。为什么这样呢?这不得不先来了解这两种复制的区别

浅复制

  • 将常引用对象的每一个成员变量的值复制到新对象中
  • 将指针类型的值,仅仅复制指针的地址,而不是复制指针所指向的内容。

第二点就是问题所在,复制出来的对象里的指针与原对象里的指针还共用着同一块内容。万一其中一个对象释调用了析构函数释放了它的内容。那么对于另外一个对象来说,它复制过来的指针类型所指向的内容已经不存在了,这时就会引发内存错误。

深复制

  • 将常引用对象的每一个成员变量的值复制到新对象中
  • 将指针类型所指向的内容进行复制,重新开辟空间进行保存

因此浅复制与深复制的区别就在于对指针类型的处理上面。

如果没有定义复制构造函数,会在复制对象时调用默认复制构造函数,进行的就是浅复制。因此在对包含指针成员的对象进行复制时,必须要定义复制构造函数,使复制后的对象指针成员有自己的内存空间,即进行深复制。这样可以避免内存泄露或指针使用错误。

class Person {
public:
    int id = 0;
    Person(int a):id(a){}

};

int main()
{
    Person aa = d;
    Person person1(aa); // 调用默认复制构造函数,进行浅复制
    Person person2 = aa;  // 调用默认复制构造函数,进行浅复制
    return 0;
}