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