C++ 构造函数与析构函数

目录

一、什么是构造函数与析构函数?

二、构造函数与析构函数

1.构造函数

(1)构造函数的要求

(2) 构造函数的类型

(3)比较特殊的构造函数——拷贝构造函数 

(4)拷贝构造函数的注意点 

2.析构函数 

析构函数的要求

三、编译器提供构造函数的规则 


 

一、什么是构造函数与析构函数?

当我们创建一个类并且将它实例化成一个对象的时候,在创建对象的时候,若是我们没有指定构造函数,编译器会默认提供一个无参构造函数并调用它,默认的构造函数中没有东西能让给我们显示的看到它的调用情况,但是它是是实实在在存在的;而析构函数就是在这个对象的生命周期结束的时候被调用,在调用析构函数后,这个实例化的对象就会被销毁

二、构造函数与析构函数

1.构造函数

#include<iostream>
using namespace std;
class Circle {
public:
	Circle() {
		cout <<"我调用了Circle类的构造函数" << endl;
	}
public:
	int R = 3;
	const int pi = 3;
};
int main() {
	Circle c1;
}

其中,在类中声明在public权限中的Circle函数就是这个类的构造函数,在程序调用对象的时候会由编译器自动调用

(1)构造函数的要求

  1. 构造函数名与类名一致;
  2. 构造函数无返回值,函数名前不需要加上viod,int一类的返回类型;
  3. 构造函数有参数,因此可以发生函数重载;
  4. 只被调用一次。

(2) 构造函数的类型

  1. 按照是否传入参数分为:有参构造无参构造;
  2. 按照构造函数的类型分为:普通构造拷贝构造。  

(3)比较特殊的构造函数——拷贝构造函数 

 

#include<iostream>
using namespace std;
class Circle {
public:
	Circle() {
		cout <<"调用了Circle类的构造函数" << endl;
	}
	Circle(const Circle& c) {
		
		cout << "调用了Circle类的拷贝构造函数" << endl;
	}
	~Circle() {
		cout << "调用了Circle类的析构函数" << endl;
	}
public:
	int R = 3;
	const int pi = 3;
};
void text01(Circle c) {};
int main() {
	Circle c1;
	text01(c1);
}

运行这段代码我们不难知道,由于函数text01使用的是值传递的方式传递参数,因此我们在调用text01时创建了一个新的临时的局部变量在函数中,因此调用了一次拷贝构造函数,在函数结束时,编译器由自动调用了一次析构函数去销毁这个临时变量。56df9f4ecbe446a6a2cca654eb67039e.png

 拷贝构造函数何时被调用? 

  1. 以值传递的形式给函数参数传值的时候;
  2. 用一个已经存在的对象去初始化一个新对象的时候;
  3. 以值的方式返回一个局部对象的时候

(4)拷贝构造函数的注意点 

拷贝构造函数的形参一定要是引用类型(&),这是确保在调用拷贝构造函数的时候使用的是引用传参,确保传入拷贝构造函数的参数不会在其中被误操作,可以思考一下如果使用的是值传递的话,首先编译器会直接报错,如果它不给报错呢?在调用拷贝构造函数的时候要先对传入的参数进行拷贝,这个过程就需要调用拷贝构造函数,那岂不是就进入了一个死循环?

#include<iostream>
using namespace std;
class Circle {
public:
	Circle() {
		cout <<"调用了Circle类的构造函数" << endl;
	}
	Circle(Circle& c) {
		cout << "" << endl;
		cout <<"传入的参数c1的地址是" << &c << endl;
		cout << "调用了Circle类的拷贝构造函数" << endl;
	}
	~Circle() {
		cout << "调用了Circle类的析构函数" << endl;
	}
public:
	int R = 3;
	const int pi = 3;
};
void text01(Circle c) {
	cout <<"临时变量的地址是" << &c << endl;
};
int main() {
	Circle c1;
	cout << &c1 << endl;
	text01(c1);
}

06cbb2e5aafe487a98f8ac23268da909.png

通过这段代码,我们这样可以很直观的看出地址的变化情况,更利于我们理解拷贝构造函数。

2.析构函数 

析构函数就是当我们实例化出来的这个对象结束生命周期时被调用的一个函数,在析构函数被调用之后,这个对象也就不存在了。

#include<iostream>
using namespace std;
class Circle {
public:
	Circle() {
		cout <<"我调用了Circle类的构造函数" << endl;
	}
	~Circle() {
		cout << "我调用了Circle类的析构函数" << endl;
	}
public:
	int R = 3;
	const int pi = 3.14;
};
int main() {
	Circle c1;
}

析构函数会由编译器默认提供,但是我们也可以自己去编写它。

  • 析构函数的要求

  1. 跟构造函数一样,没有返回值也没有返回类型;
  2. 函数名跟类名一致,并且一定要在函数名前加上一个”~”,如果没有这个“~”,这个函数就是构造函数了;
  3. 不能有参数,因此析构函数不能发生函数重载
  4. 只被调用一次。

三、编译器提供构造函数的规则 

一般情况下,编译器至少提供三个默认函数,分别是默认构造函数默认析构函数默认拷贝构造函数。 

规则:如果我们写了普通构造函数,那么编译器不再提供默认构造函数,但是依然提供默认拷贝构造函数与默认析构函数;如果我们写了默认拷贝构造函数,那么编译器就不再提供其他的普通构造函数了。

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

默示MoS

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值