欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

构造函数和析构函数

程序员文章站 2022-06-01 13:02:56
...

每日文摘

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


构造函数和析构函数

构造函数和析构函数
注意:程序会在对象销毁前自动调用析构函数
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);
}

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

总结

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

相关标签: C++