构造函数

构造析构

一、构造函数

1、介绍

构造函数,它是一种特殊的函数,主要用来在创建对象时初始化对象,即为对象的成员变量赋初始值。

2、构造函数的定义:

//1 构造函数名和类名相同
//2 构造函数没有返回值类型,和返回值
//3 构造函数可以重载,需要满足函数重载的条件
class student
{
public:
	student(){}			//无参构造(默认构造)
	student(int a){}	//有参构造(带参构造)
};

3、构造函数的调用时机

//1 在创建一个新的对象的时候会调用
//调用无参构造
student stu;
student *p = new student;
//调用带参构造
student stu(1);
student *p = new student(1);

4、构造函数的特点

/*
*	1 如果一个类中没有显示的给出构造函数,系统会自动给出一个缺省的(隐式)什么都不干的构造函数
*	2 如果类中有多个构造函数,那么通常会有不同的参数列表和函数体
*	3 如果用户提供了无参(带参)构造,那么系统就不再提供默认构造
*	4 类中如果只有带参构造,没有无参构造,那么就不能调用默认构造的方式初始化对象,想用这种方式初始化对象就要提供无参构造
*
*
*/

5、拷贝构造(一种特殊的构造)

//1 拷贝构造是一种特殊的构造函数,用自身这种类型来构造自身
//例;
student stu1;
student stu2 = sut1;//在这一句就会调用拷贝构造
拷贝构造的定义:

​ 1 没有写拷贝构造,系统会提供一个隐式的拷贝构造,而这个拷贝构造的操作,我们可以理解为,是用 ‘ = ’ 号一个一个的将存在于对象中的数据成员赋值给新创建的对象中。

//	2 自定义拷贝构造
//		类名(const 类名& 引用名){}
//	这里的const不加也可以,但是这里是拷贝,也就是复制的意思,所以加上,防止被改
//	在函数体里面通常的做法是逐一拷贝传进来的对象的成员,赋值给新的对象,当然也可以自己定义内容

//例:
class Student
{
	int id;
public:
	Student(const Student&stu)
	{
	this->id=stu.id;
	//把传进来对象的id赋值给当前调用对象的id
	}
}

拷贝构造的调用:
//1 在用同种类的对象,去初始化另一个对象的时候(注意是在定义对象初始化,不是赋值)
Student stu1;
Student stu2=stu1;//显示调用拷贝构造
Student stu3(stu2);//隐式调用拷贝构造
Student *pStu=new Student(stu3);

//2 在函数传参时,函数的形参是类对象
void fun(Student stu){}
fun(stu1);//在函数调用传参时调用拷贝构造

//3 如果一个函数的返回值类型是对象,在函数调用结束,返回对象的时候调用拷贝构造
Student fun1(Student stu)
{
    return stu;
}
//这里在函数调用的时候会调用两次拷贝构造,函数传参一次,函数返回时一次

//函数返回时再次调用拷贝构造的原因:stu形参是属于栈区的,不能return出来,出了函数就直接被释放了,所以想要返回出来,就要再拷贝一次。
6、深拷贝与浅拷贝

1、浅拷贝

​ 浅拷贝构造我们不写,系统也会提供一个默认的拷贝构造,而这个拷贝构造的操作,我们可以理解为,是用 ‘ = ’ 号一个一个的赋值的,我们将之称为,浅拷贝。在用指针的时候我们就知道两个同等类型的指针之间用 ‘ = ’ 号赋值,是两个指针的地址指向同一个内存,那么就可能会存在一个问 题,就是两个对象的指针都指向同一个内存,那么如果其中一个对象把该内存释放了,就会导致另外一个对象的指针变成野指针。

2、深拷贝

​ 也就是在有上述问题的时候才需要深拷贝,而深拷贝做的事情也就是自己定义拷贝构造,给新的对象的指针申请内存,来存内容,而不是两个对象的指针指向同一个内存

//示例:
class Student
{
	char *name;
public:
	Student(char *name)
	{
	this->name=new char[strlen(name)+1];//加1是为了保存'\0'
	strcpy(this->name,name);
	}
	Student(const Student& stu)
	{
		//这个自定义拷贝构造函数做的事,其实就是给新对象的指针申请		内存来存数据,如果有其他成员,那么也要记得赋值
	this->name=new char[strlen(stu.name)+1];//加1是为了存'\0'
	strcpy(this->name,s
           tu.name);
	}
}

什么时候要自己写拷贝构造?

​ 类中有动态申请内存的时候,必须要写。

posted @ 2021-11-09 15:45  宣哲  阅读(1648)  评论(0编辑  收藏  举报