拷贝构造函数

拷贝构造是特殊的构造类型,也会影响类内是否会创建默认构造函数。

单纯只有拷贝构造也可以创建对象

静态数据成员无法在类内初始化,只能在类外(main函数内也不行,得在静态全局区),但可以通过相应对象的接口进行赋值。

拷贝构造是一种通过自身类型来构造自身的构造函数,用户可以自定义拷贝构造,系统会默认给出:

1
2
3
4
5
class student{
public:int a=2;
}
student stu1;
student stu2=stu1;

这里系统给出了一个默认拷贝构造,把stud1的数据成员一个一个地赋值给stu2;

创建方法:

1
2
3
4
5
6
class student{
public:int a=2;
student(const student& stu){
this->a=stu.a;
}
}

注意:①函数名与类名一致

​ ②参数必须是本类型的一个引用变量

​ ③因为只是复制,加上const保险一些

调用时机

一、用同类型对象初始化对象时(只是在定义新对象时可以)

1
2
student stu1;
student stu2=stu1;//这个方式也是适用与自定义拷贝构造的

二、类为函数形参类型时

1
void test(student a){};

对象作为形参传入时,实际上传入的是student类型对象的一个副本,自然调用了拷贝构造。

三、类为函数返回值类型时

1
2
3
student test(student a){
return a;
};

对象返回时实际上返回的时对象a的一个副本,事实上这里调用了两次拷贝构造,使用返回的是初始传入对象的副本的副本。

注意问题:浅拷贝与深拷贝

浅拷贝

我们在使用系统默认拷贝函数时,对象内数据成员是一个一个“=”过去的。这种拷贝正常情况不会出现问题,但是一旦涉及指针,就会出现问题。指针与指针相等实际上仍然指向的是同一段内存,原来对象的内容并没有复制过去,甚至在原对象释放之后,新对象中的指针还会变成野指针

深拷贝

我们一般使用浅拷贝就够了,一旦涉及指针,那就需要动态申请内存,所以需要自定义拷贝函数,使用深拷贝

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class student{
public:
char* name;
student(char* name)//构造函数
{
this->name=new char[strlen(name)+1];
strcpy(this->name,name)
}

student(const student& stu){//拷贝构造
this->name=new char[strlen(stu.name)+1];//动态分配内存
strcpy(this->name,stu.name);
}
};

问题:拷贝构造可以有多个吗?

不能,这个和析构函数是一个道理的,因为拷贝构造函数析构都是系统自动调用的,不能让系统陷入为难的选择之中。,不能重载。