构造函数和析构函数

介绍

在类中我们经常需要在程序开始时对程序进行初始化,而在程序结束时我们经常需要内存的清理,这将关系到我们程序的安全问题

在对象没有进行初始化时我们无法确认他的具体数据和状态,使用时也是极其危险的,而在使用完对象后没有进行及时清理也会导致留下极大的安全隐患

而c++在程序中就内置了构造函数和析构函数来帮我们处理这个”准备工作“以及程序使用后的”烂摊子“,他们可以在程序运行时初始化对象,并且在程序运行完后进行清理。

在c++中构造函数和析构函数是编译器的强制要求,如果我们没有提供独影的函数,那么编译器会自动提供的构造函数和析构函数并且是空实现

构造函数


格式语法如下:

1
类名(){}

注意

  1. 构造函数没有返回值也不需要写数值返回类型
  2. 构造函数有参数,也可以与普通函数一样可以发生重载
  3. 程序运行时会自动调用构造函数且只调用一次,不需要手动指定。
  • 作用:主要用于创建对象时为对象的队员属性赋值,构造函数由编译器自动调用

分类:

  1. 有参函数和无参函数(从参数看)
  2. 普通构造和拷贝构造(从类型看)

三种调用方式:

  1. 括号的法。
  2. 显示法。
  3. 隐式转换法。

规则:

在编译器中如果写了普通有参构造函数则编译器会自动提供拷贝构造函数而不会提供无参构造函数,如果自己写了拷贝构造函数则编译器不会提供普通构造函数和拷贝构造函数。

在cpp中一般有三种情况时使用拷贝函数:

  1. 使用一个已经初始化完毕的对象来初始化一个新对象
  2. 值传递方式给函数参数传值
  3. 以值返回局部对象
1
2
3
4
5
6
7
8
9
10
11
12
13
//拷贝构造函数示例

class Car
{
protected:
int number;

public:
Car(const Car &p)//将传进来的对象的age属性拷贝一份为age赋值
{
number=p.number
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

int main()
{
//括号法
Car c1(10);
Car c2(c1);//拷贝c1内容进入c2
//显示法
Car c3=c1;//将c1的参数全部赋值给c3
Car c4(10);//直接赋值给c4 number 为有参构造

Car c5=Car(10)//右侧为匿名对象,可以将数据赋值给左侧
//隐式法
Car c6=10;//这里会将值肢解赋给属性中的number
}
---------------------------------------------------------
在这里上面的c实际为c的参数,而下面的c实际为一个对象
void work(Car c)
{

}

int main()
{
Car c(10);
work(c)
}

在上述代码中有一个Car(10)的对象,为匿名对象,匿名对象在程序执行完后会直接被程序回收,在使用匿名函数时不要使用拷贝函数初始化对象

浅拷贝和深拷贝

浅拷贝:简单的赋值操作

深拷贝:在堆区重新申请空间进行拷贝操作

注意:在程序提供的拷贝函数中会对其直接进行赋值,此种操作为浅拷贝,如果含有指针的数据存在,则需要自己手动写拷贝函数并且在拷贝函数中手动开辟空间并且进行赋值

析构函数


格式语法如下:

1
~类名(){}

注意:

  1. 析构函数没有返回值也不需要返回类型
  2. 析构函数与构造函数区别在于前面加上了~
  3. 析构函数不可以有参数所以不能发生重载
  4. 在程序销毁前自动调用,无需手动操作

用法:

析构函数用法很简单,不需要参数,一般是用来释放空间,销毁地址使用。


资料参考

b站的黑马程序员