C++类四大隐藏函数详解(构造函数、析构函数、拷贝构造、赋值函数)

构造函数传送门

一、析构函数

1、什么是析构函数

​ 与构造函数一样也是一种特殊的成员函数,它会在对象释放的时候自动调用,负责一些收尾工作,如:保存数据、释放资源等。

2、函数格式

~类名(void)
{
    
}

3、析构函数的任务

​ 负责释放在构造函数中获取到的所有资源。

​ 执行过程:

​ 1、先执行析构函数本身代码

​ 2、调用成员变量的析构函数

​ 3、调用父类的析构函数

  • 注意:析构函数与构造函数的执行顺序刚好相反
#include <iostream>
using namespace std;

class Test
{
public:
	Test(void)
	{
		cout<<"我是构造函数"<<endl;
	}
	~Test(void)
	{
		cout<<"我是析构函数"<<endl;
	}
};

void func(void)
{
	Test* t = new Test;
	cout<<"-------"<<endl;
	delete t;
}
int main(int argc,const char* argv[])
{
	int n=3;
	while(n--)
	func();
}

二、缺省的析构函数,构造函数

1、 定义

在设计一个类时,如果没有显示实现构造函数与析构函数,编译器 会自动生成它们,也叫缺省的构造和析构函数。

但生成的并不是真正语法意义上的函数,而是功能意义上的函数。

编译器做为可执行指令的生成着,它有能力直接生成某些功能的二进制指令,不需要借助语言上的函数完成某些任务。

2、 什么时候需要显示实现构造函数

  1. 有成员需要初始化
  2. 需要一些参数做一些准备工作
  3. 需要在对象使用之前准备一些资源.如:申请一些堆内存

3.、什么时候需要显示实现析构函数

缺省的析构函数会自动释放编译器能看得到的所有资源。如:成员变量,类成员,父类

  1. 保存一些数据
  2. 成员变量中有指针,且指向堆内存。

三、类对象 创建过程与释放内存总结

创建:

分配内存 -> 父类构造 -> 成员构造 -> 自己的构造(初始化成员,申请准备内存等)

​ 父类构造:按照继承表的顺序从左到右依次执行父类构造函数

​ 成员构造:按照成员的声明顺序,从上到下依次执行成员变量的构造函数

释放:

自己的析构函数(保存数据,释放堆内存等) -> 成员析构 -> 父类的析构 -> 释放内存(对象)

​ 成员析构:按照声明的顺序,从下到上依次执行成员变量的析构函数

​ 父类析构:按照继承表从右到左依次执行父类的析构函数。

四、拷贝构造函数(赋值构造)

什么是拷贝构造函数

​ 是一种特殊的构造函数,当使用一个对象初始化另一个新的对象时,就会调用隐藏的拷贝构造函数,它也是类自带构造函数之一,由编译器自动生成。

拷贝构造格式

类名(const 类名& 变量名)
{
    
}

调用拷贝构造

  1. 类名 对象 = 对象
  2. 使用对象作为函数的参数时(不使用引用)

拷贝构造的任务

​ 负责把旧的类对象中的成员拷贝给新的对象(默认,浅拷贝)。

什么时候显式使用拷贝构造?

​ 当类中有成员是指针,且该指针指向了一块堆内存,此时拷贝构造应该拷贝指针所指向的内存(深拷贝),而默认的浅拷贝只拷贝指针变量的值,这时候会导致指针指向的内存被delete从而内存崩溃,因此应该显示地拷贝构造。

#include <iostream>
using namespace std;

class Test
{
	int num;
public:
	Test(int num)
	{
		this->num = num;
	}

	Test(Test& t)
	{
		num = t.num;
		cout << "我是拷贝构造" << endl;
	}

	void show(void)
	{
		cout << num << endl;
	}
};

void func(Test t)
{
	cout << __func__ << endl;
}

int main(int argc,const char* argv[])
{
	Test t(100);

	Test t1 = t;	// 调用拷贝构造
	t.show();
	t1.show();

	func(t);
}

七、赋值函数(赋值运算符)

什么是赋值函数

​ 在C++中是把运算符当做函数处理的,当一个对象给另一个对象赋值时就会自动调用该函数

赋值函数格式

& operator=(const& that)
{
    
}
#include <iostream>
using namespace std;

class Test
{
	int num;
public:
	Test(int num)
	{
		this->num = num;
	}

	void show(void)
	{
		cout << num << endl;
	}

	Test& operator=(const Test& that)
	{
		num = that.num;
		cout << "我是赋值函数" << endl;
		return *this;
	}
};

int main(int argc,const char* argv[])
{
	Test t(100);
	Test t1(0);
	(t1 = t).show(); 		//调用赋值函数
}

什么时候调用

​ 对象 = 对象;

赋值函数的任务

​ 与拷贝构造函数一样,负责把一个对象的内存拷贝给另一个对象(浅拷贝)。

什么时候显式实现赋值函数:

​ 当需要显式实现拷贝构造时,就应该显示实现赋值函数。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值