构造函数和析构函数

每日文摘

我感冒了 ,因为我对你没有抵抗力。


构造函数和析构函数

在这里插入图片描述
注意:程序会在对象销毁前自动调用析构函数
1.析构函数通常作用是将在堆区开辟的内存释放
2.先构造的后析构

一. 构造参数的分类

按有参无参分为 :有参构造无参构造
按类型分:普通构造拷贝构造

class stu {
public:
	//无参构造
	stu() {
		cout << "无参构造" << endl;
	}
	//有参构造
	stu(int p) {
		cout << "有参构造" << endl;
	}
	//拷贝构造
	stu(const stu &p) {
		cout << "拷贝构造构造" << endl;
	}
	~stu() {
		cout << "析构函数" << endl;
	}
};

在这里插入图片描述
在这里插入图片描述
反过来了


二. 构造函数的调用

方法:
1.括号法(常用)

stu p;//无参构造
stu p1(10);//有参构造
stu p2(p1);//拷贝构造

注意点:无参构造不能写成这种 stu p() 构造器会认为这是函数的声明

2.显试法

stu p1 = stu (10);//有参
stu p2 = stu(p2);//拷贝

注意 stu(10)单独写就是匿名对象,当前结束后马上析构

3.隐试法

stu p1 = 10;//stu p1=stu(10)
stu p2 = p1;//stu p2=stu(p1)

构造函数的调用规则

1.在默认情况下,编译器会至少给一个类提供三个函数
默认的构造参数无参,函数体为空
默认的析构函数无参,函数体为空
默认的拷贝构造函数,对属性进行值拷贝

2.
2.1 如果用户定义了有参构造函数,编译器将不会定义默认无参构造函数,但会定义拷贝构造函数
2.2 如果用户定义了拷贝构造函数,编译器将不会定义任何构造函数


三.拷贝函数调用的时机

1.使用一个创建完毕的对象来初始化一个对象。

stu p(10);
stu p1(p);

2.一值传递的方式给函数参数传值。

void f(stu p){
}
int main(){
  stu p(10);
  f(p);
}

函数f中的参数属于值传递,在拷贝的途中,运用到了拷贝构造函数
3.一值方式返回局部对象

stu  f(){
  stu p(10);
  return p;
}
int main(){
stu f =f();
}

因为return是拷贝了一份p,所以运用到了拷贝构造函数

浅拷贝和深拷贝

浅拷贝是指默认拷贝构造函数对对象的成员进行简单的值拷贝

但是浅拷贝会在一些情况下出现问题,我们看一下代码

class P {
public :
	int* point;
	P(int a) {
		this->point = new int(a);
	}

};
int main() {
	P p(10);
	P p1(p);
	cout <<*p.point<<endl;//10
	cout << *p.point;//10
}

到这里一切都是正常的,因为在构造函数P中用new在堆中开辟了一片内存·,需要手动去释放。那么加一个析构函数去释放

~P() {
		delete(point);
	}

将这串代码放到类P中,发现报错了
在这里插入图片描述
这是问神魔呢?
浅拷贝会把指针变量的地址复制了,而对象p和p1都会调用析构函数(先调用p1然后p,函数先执行的后析构),
然而在第一次p1调用析构函数时,就已经将那块内存释放了,p再次调用时当然会报错了。
这时就要用深拷贝了

P(const P & p) {
	this->point = new int(*p.point);
}

此时拷贝时会再开辟一款内存,所以析构时,将不会释放同一块内存了。

总结

浅拷贝:又称值拷贝,将源对象的值拷贝到目标对象中去,本质上来说源对象和目标对象共用一份实体,只是所引用的变量名不同,地址其实还是相同的。
 
深拷贝:拷贝的时候先开辟出和源对象大小一样的空间,然后将源对象里的内容拷贝到目标对象中去,这样两个指针就指向了不同的内存位置。并且里面的内容是一样的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值