前言

🎃本文介绍C++中构造函数析构函数

😋C++中常用构造函数进行对象创建时初始化操作

🤨析构函数则相反,用于处理对象销毁后善后工作

构造函数

🎉构造函数是一种特殊的成员函数创建对象时自动调用构造函数。

🎃根据构造函数的特性,我们可以使用构造函数来进行初始化操作

😋如果我们没有为类定义构造函数,编译器会默认提供一个默认构造函数(无参数,不进行任何操作,仅仅满足接口要求)。

构造函数的特点:

  • 构造函数名和类名相同

  • 构造函数没有返回值

定义构造函数

声明构造函数的方法(类名即函数名):

1
类名(参数);

定义构造函数的方法:

1
2
3
4
类型::类名(参数)
{
函数体;
}

🎃下面,通过一个例子说明:

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
#include <iostream>

using namespace std;

class Student
{
public:
int age;
int grade;
Student(int age); //声明构造函数
};

Student::Student(int age) //定义构造函数
{
this->age = age;
}

int main()
{
Student student(11); //创建对象,并调用构造函数

cout << student.age;

return 0;
}

输出结果:

1
11

我们定义了Student构造函数,参数的一个int类型的age。

❗这里需要注意的是,如果我们定义了构造函数,则默认构造函数会失效

🎁也就是说,我们必须使用Student(int)来创建对象,否则会报错。

🎃为了解决这个问题,我们可以定义一个无参的默认构造函数

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
27
28
29
30
31
32
#include <iostream>

using namespace std;

class Student
{
public:
int age;
int grade;
Student(); //声明无参的默认构造函数
Student(int age); //声明带参数的构造函数
};

Student::Student(int age) //定义带参数构造函数
{
this->age = age;
}

Student::Student() //定义无参默认构造函数
{

}

int main()
{
Student student(11); //调用带参数构造函数
Student student; //调用无参默认构造函数

cout << student.age;

return 0;
}

参数初始化表

🎃除了在函数体内对数据成员进行初始化,我们还可以使用参数初始化表进行初始化。

参数初始化表进行初始化的格式:

1
2
3
4
类名::构造函数名(参数1, 参数2):数据成员1(参数1), 数据成员2(参数2)
{

}

✨下面,通过例子说明:

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
#include <iostream>

using namespace std;

class Student
{
public:
int age;
int grade;
Student(int age); //声明构造函数
};

Student::Student(int age):age(age) //定义构造函数,使用参数初始化表
{
cout << "调用了Student构造函数,通过参数初始化表进行初始化!" << endl;
}

int main()
{
Student student(11); //创建对象,并调用构造函数

cout << student.age;

return 0;
}

输出结果:

1
2
调用了Student构造函数,通过参数初始化表进行初始化!
11

析构函数

🎃创建对象时调用构造函数,销毁对象时调用析构函数

🎃如果我们的对象申请了内存空间,在对象销毁时需要我们对内存进行回收,否则会造成内存溢出

😐同构造函数一样,析构函数也是一个特殊的成员函数

析构函数的特点:

  • 函数名为~类名

  • 没有返回值

  • 没有参数

定义析构函数

声明析构函数的方法:

1
~类名();

定义析构函数的方法:

1
2
3
4
类名::~类名()
{

}

下面通过一个例子说明:

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
27
28
#include <iostream>

using namespace std;

class Student
{
public:
Student(); //声明构造函数
~Student(); //声明析构函数
};

Student::Student() //定义构造函数
{
cout << "调用了Student构造函数" << endl;
}

Student::~Student() //定义析构函数
{
cout << "调用了Student析构函数" << endl;
}

int main()
{
Student* stu = new Student; //创建Student对象
delete stu; //销毁Student对象

return 0;
}

输出结果:

1
2
调用了Student构造函数
调用了Student析构函数

😐除了使用new和delete,按照以往创建对象的方式,在对象生命周期结束后进行销毁时也会调用析构函数。

拷贝构造函数

😐创建一个新对象时,用已有对象为其初始化时,编译器调用拷贝构造函数

例如:

1.创建对象时,使用已有对象对其初始化。

2.函数调用时,对象作为实参传递给函数。

🎃拷贝构造函数的任务:把B对象的数据成员复制给A对象的数据成员。

浅拷贝

🎡浅拷贝类似于函数调用时候的值传递,即把B对象数据成员的值拷贝给A对象的数据成员。

🛒当B对象申请了内存空间后,某个数据成员指向这块内存空间。

🎉进行浅拷贝后,A对象的数据成员也指向这一块内存空间,并没有申请新的内存空间

🎶也就是说,进行浅拷贝后,A、B数据成员指向了一块相同的内存空间共用这块数据

深拷贝

🧧深拷贝则不同,上述情况下:

🎉A会申请一块内存空间,这块空间保存B对象数据成员指向的内存空间相同的值

🛒也就是说,A有了自己独立的一块内存空间,这个空间内容和B对象申请的空间内容一致。

定义拷贝构造函数

🎡拷贝构造函数的形参必须是类对象的引用,最好是常引用

拷贝构造函数的声明:

1
类名(const 类名& 变量名);

拷贝构造函数的定义:

1
类名::类名(const 类名& 变量名);

😅某些情况下,默认的拷贝构造函数不能满足我们的需求。

🐾这时候,我们可以通过重写拷贝构造函数的方式进行拷贝。

🎎具体情况很复杂,有的地方甚至还涉及STL的符号重载,这里不再具体讨论,后期会另发博客单独进行讨论。

总结

🎉主要介绍了构造函数、拷贝构造函数、析构函数。

🎡构造函数在创建对象时调用,析构函数在销毁对象时调用。

🚩创作不易,本人保证所发文章均为精心筹备。

💌如需转载,请保留作者信息和博客地址。

📡如果感觉博客对你略有帮助,欢迎转发给你的朋友,让他们加入到技术风暴中来吧!