【Cpp】类和对象#构造函数 析构函数

标题:【Cpp】类和对象#构造函数 析构函数

@水墨不写bug

(图片来源于网络)


 正文开始:

(一)构造函数

        构造函数是特殊的成员函数,需要注意的是,构造函数虽然名称叫构造,但是构造函数的主要任务并不是开空间创建对象,而是初始化对象。

其特征如下:
1. 函数名与类名相同。
2. 无返回值。(不需写为void)


class A {
public:
	A()//函数名和类名相同,且不需要写返回值类型
	{
		_a = 1;
		_c = 't';
	}
	
private:
	int _a;
	char _c;
	stack st1;
};


3. 对象实例化时编译器自动调用对应的构造函数。(自动初始化,省去了Init()函数)

class A {
public:
	A()//函数名和类名相同
	{
		_a = 1;
		_c = 't';
	}	
private:
	int _a;
	char _c;

};
int main()
{
	A a1;	
	return 0;
}

(上述程序中,在创建a1后自动调用A(),将_a,_c初始化)
4. 构造函数可以重载。(构造函数可以有多个,也就是对象的初始化方式可以有多个

        简单举一个例子:


class B {
public:
	B()
	{
		_a = 1;
		_c = 't';
		_arr = (int*)malloc(sizeof(int));
	}
	B(int n)
	{
		_arr = (int*)malloc(sizeof(int) * n);
		_a = 1;
		_c = 't';
	}

private:
	int _a;
	char _c;
	int* _arr;
};

int main()
{
	B b1;
	B b2(100);
	
	return 0;
}

 (        b1对象没有传参,调用没有参数的构造函数;b2传了一个参数n,调用有一个参数的默认构造,可以指定开辟空间的大小

        但是对于下面的重载,情况就有所不同了:


class B {
public:
	B()
	{
		_a = 1;
		_c = 't';
		_arr = (int*)malloc(sizeof(int));
	}
	B(int n = 8)
	{
		_arr = (int*)malloc(sizeof(int) * n);
		_a = 1;
		_c = 't';
	}

private:
	int _a;
	char _c;
	int* _arr;
};

这两个函数显然构成函数重载,因为他们的参数个数不同。但是在不传参调用的时候,会导致编译器报错,因为编译器无法区分无参调用调用的具体是哪一个函数


5. 如果类中没有显式定义构造函数,则C++编译器会自动生成一个无参的默认构造函数,一旦用户显式定义编译器将不再生成。


6.对于自动生成的默认构造函数,有如下性质:

        i,自定义类型(int,float,int*等)不做处理,仍然是随机值;

        ii,对于自定义类型(struct,class声明中的类),转跳到这个自定义类型的对应的构造函数中去,自动调用自定义类型的构造函数。

7.什么是默认构造,总结下来有如下几种情况:

        i,自己没有写,编译器自动生成的的构造函数是无参数的构造函数,也就是默认构造;

        ii,自己写了一个函数,但是没有参数,也可以被编译器识别为默认的构造函数,这时编译器就不会再自动生成一个构造函数了;

        iii,自己写了一个函数,有参数,但是是全缺省的参数,这也可被编译器识别为默认的构造函数,这时编译器就不会再自动生成一个构造函数了;

(注意:无参构造函数、全缺省构造函数、我们没写编译器默认生成的构造函数,都可以认为是默认构造函数。但是要注意编译器生成的构造函数不会处理内置类型)

(二)析构函数

        析构函数:与构造函数功能相反,析构函数不是完成对对象本身的销毁,局部对象销毁工作是由编译器完成的。而对象在销毁时会自动调用析构函数,完成对象中资源的清理工作。

析构函数是特殊的成员函数,其特征如下:
1. 析构函数名是在类名前加上字符 ~。(~表示取反,暗示了清理资源的工作)
2. 无参数无返回值类型。(无需写void)

class stack{
public:
	stack(int n = 4)//函数名和类名相同
	{
		_arr = (int*)malloc(sizeof(int) * n);
		_top = 0;
		_capacity = 0;
	}
	~stack()//函数名和类名相同,不需要写返回值类型
	{
		free(_arr);
		_top = 0;
		_capacity = 0;
	}
private:
	int* _arr;
	int _top;
	int _capacity;
};


3.对象生命周期结束时,C++编译系统系统自动调用析构函数。


4.一个类只能有一个析构函数。若未显式定义,系统会自动生成默认的析构函数。注意:析构函数不能重载,也就是说析构只有一种方式。


5.对于自动生成的析构函数,有如下性质:

        i,对于自定义类型(int,float,int*等)不做处理,自定义类型本身不需要资源的释放;

        ii,对于自定义类型(struct,class声明中的类),转跳到这个自定义类型的对应的析构函数中去,自动调用自定义类型的析构函数。

6.从上述特性可以得出:如果类中没有申请资源时,析构函数可以不写,直接使用编译器生成的默认析构函数,比如Date类;有资源申请时,一定要写析构函数,否则会造成资源泄漏,比如Stack类。

总结:

        默认生成虽然好,但是如果默认生成的构造/析构函数在调用时由于只处理自定义类型,如果自定义类型的构造/析构没有写,那么即使是默认生成的函数,本质上也是没有做任何工作。

class stack{
public:
	stack(int n = 4)//函数名和类名相同
	{
		_arr = (int*)malloc(sizeof(int) * n);
		_top = 0;
		_capacity = 0;
	}
	/*
	~stack()
	{
		free(_arr);
		_top = 0;
		_capacity = 0;
	}
	*/
private:
	int* _arr;
	int _top;
	int _capacity;
};

class A {
public:
	A()//函数名和类名相同
	{
		_a = 1;
		_c = 't';
	}
	
private:
	int _a;
	char _c;
	stack st1;
};

(虽然A类没有写析构,但是编译器会默认生成,处理A中需要释放的资源st1;但是st1的类没有写析构函数,也只是调用默认生成的析构,这时,st1中的动态申请的堆空间就无法释放了,造成内存泄漏)

        所以,我们能自己写的构造/析构,就最好自己写,不要过分依靠编译器默认生成。 


完·~ 

未经作者同意禁止转载

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/589994.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

nginx变量自定义日志收集

内置变量 $remote_addr;存放了客户端的地址,注意是客户端的公网IP,也就是一家人访问一个网站,则会显示为路由器的公网IP。 $args;变量中存放了URL中的指令 [rootlocalhost conf.d]# cat pc.conf server {listen 80;se…

数组的扩容与缩容

数组的扩容与缩容 文章目录 数组的扩容与缩容数组的扩容内存分析 数组的缩容内存分析内存分析 数组的扩容 数组扩容是指当原有数组的空间不足以容纳更多的元素时,创建一个新的、长度更大的数组,并将原数组中的元素复制到新数组中,然后更新原…

C++入门第二节--关键字、命名空间、输入输出

点赞关注不迷路!本节涉及c入门关键字、命名空间、输入输出... 1. C关键字 C总计63个关键字,C语言32个关键字 asmdoifreturntrycontinueautodoubleinlineshorttypedefforbooldynamic_castintsignedtypeidpublicbreakelselongsizeoftypenamethrowcaseen…

如何完全卸载QT

第一步,用QT自带的软件卸载QT 第二步,卸载下面路径的所有QT配置 C:用户/(你的用户)/AppData/Local/目录下所有与Qt相关内容 C:用户/(你的用户)/AppData/Local/Temp/所有与Qt相关内容 C:用户/(你的用户)/AppData/Roaming/所有与Qt相关内容

C 深入指针(2)

目录 1 野指针 1.1 成因 1.2 如何规避野指针 2 assert 断言 2.1 用法 2.2 assert 的优点 2.1 assert 的缺点 3 小注解 3.1 Debug 和 Release 1 野指针 【概念】: 野指针就是指针指向的位置是不可知的(随机的、不正确的、没有明确限制的&#…

场景文本检测识别学习 day06(Vi-Transformer论文精读、MAE论文阅读)

Vi-Transformer论文精读 在NLP领域,基于注意力的Transformer模型使用的非常广泛,但是在计算机视觉领域,注意力更多是和CNN一起使用,或者是单纯将CNN的卷积替换成注意力,但是整体的CNN 架构没有发生改变VIT说明&#x…

与 Apollo 共创生态:企业解决方案Apollo X 9.0,七载同舟,携手远航,视频简说

目录 介绍背景方案与项目Apollo 开源项目Apollo X 企业解决方案落地因素助力企业落地流程 预置套件需求定义功能定义场景用例融合技术面向园区功能安全Cyber RT企业硬件套件 开发工具链研发迭代范式协同研发工具链标定工具地图工具仿真平台数据闭环 企业合作模式合作方式 共创计…

[初阶数据结构】时间复杂度与空间复杂度

前言 📚作者简介:爱编程的小马,正在学习C/C,Linux及MySQL。 📚本文收录于初阶数据结构系列,本专栏主要是针对时间、空间复杂度,顺序表和链表、栈和队列、二叉树以及各类排序算法,持续…

nuxt3使用记录六:禁用莫名其妙的Tailwind CSS(html文件大大减小)

发现这个问题是因为,今天我突然很好奇,我发现之前构建的自动产生的200.html和404.html足足290k,怎么这么大呢?不是很占用我带宽? 一个啥东西都没有的静态页面,凭啥这么大!所以我就想着手动把他…

ICode国际青少年编程竞赛- Python-1级训练场-基础训练2

ICode国际青少年编程竞赛- Python-1级训练场-基础训练2 1、 a 4 # 变量a存储的数字是4 Dev.step(a) # 因为变量a的值是4,所以Dev.step(a)就相当于Dev.step(4)2、 a 1 # 变量a的值为1 for i in range(4):Dev.step(a)Dev.turnLeft()a a 1 # 变量a的值变为…

未来科技的前沿:深入探讨人工智能的进展、机器学习技术和未来趋势

文章目录 一、人工智能的定义和概述1. 人工智能的基本概念2. 人工智能的发展历史 二、技术深入:机器学习、深度学习和神经网络1. 机器学习2. 深度学习3. 神经网络 三、人工智能的主要目标和功能1. 自动化和效率提升2. 决策支持和风险管理3. 个性化服务和预测未来 本…

DHCPv4_CLIENT_ALLOCATING_01: 在其本地物理子网上广播DHCPDISCOVER消息

测试目的: 确保客户端能够在其本地物理子网上广播DHCPDISCOVER消息。 描述: 该测试用例旨在验证DHCP客户端是否能够正确地在其本地物理子网上广播DHCPDISCOVER消息,以便进行IP地址的自动分配。 测试拓扑: 测试步骤&#xff1a…

机器学习:深入解析SVM的核心概念【三、核函数】

核函数 **问题一:为什么说是有限维就一定存在高维空间可分呢?**原始空间与特征空间为什么映射到高维空间可以实现可分核函数的作用 **问题二:最终怎么得到函数**从对偶问题到决策函数的步骤:结论 **问题三:为什么说特征…

【Proteus】LED呼吸灯 直流电机调速

1.LED呼吸灯 #include <REGX51.H> sbit LEDP2^0; void delay(unsigned int t) {while(t--); } void main() {unsigned char time,i;while(1){for(time0;time<100;time){for(i0;i<20;i){LED0;delay(time);LED1;delay(100-time);}}for(time100;time>0;time--){fo…

003 redis分布式锁 jedis分布式锁 Redisson分布式锁 分段锁

文章目录 Redis分布式锁原理1.使用set的命令时&#xff0c;同时设置过期时间2.使用lua脚本&#xff0c;将加锁的命令放在lua脚本中原子性的执行 Jedis分布式锁实现pom.xmlRedisCommandLock.javaRedisCommandLockTest.java 锁过期问题1乐观锁方式&#xff0c;增加版本号(增加版本…

GPT-1

GPT 系列是 OpenAI 的一系列预训练模型&#xff0c;GPT 的全称是 Generative Pre-Trained Transformer&#xff0c;顾名思义&#xff0c;GPT 的目标是通过 Transformer&#xff0c;使用预训练技术得到通用的语言模型。目前已经公布论文的有 GPT-1、GPT-2、GPT-3。 最近非常火的…

腾讯云ubuntu新建用户后,命令行只显示$

这是因为&#xff0c;新建用户命令行解释器默认是sh&#xff0c;需要手动切换为bash&#xff0c;bash可以认为是sh的加强版本。 所以我们只需要将&#xff0c;shell切换为bash就好了。 切换到root 修改配置文件 vim/etc/bash 将sh修改为bash

AcWing 3194:最大的矩形 ← 笛卡尔树

【题目来源】https://www.acwing.com/problem/content/3197/【题目描述】 在横轴上放了 n 个相邻的矩形&#xff0c;每个矩形的宽度是 1&#xff0c;而第 i&#xff08;1≤i≤n&#xff09;个矩形的高度是 hi。 这 n 个矩形构成了一个直方图。 例如&#xff0c;下图中六个矩形的…

类和对象【四】运算符重载

文章目录 运算符重载的概念运算符重载&#xff08;函数&#xff09;返回值类型&#xff1a;任意类型函数名&#xff1a;operator已有操作符 运算符重载&#xff08;函数&#xff09;的特点和注意点3个比较特殊的运算符重载赋值运算符&#xff08;&#xff09;重载返回值类型和返…

Linux CentOS7部署ASP.NET Core应用程序,并配置Nginx反向代理服务器和Supervisor守护服务

前言&#xff1a; 本篇文章主要讲解的是如何在Linux CentOS7操作系统搭建.NET Core运行环境并发布ASP.NET Core应用程序&#xff0c;以及配置Nginx反向代理服务器。因为公司的项目一直都是托管在Window服务器IIS上&#xff0c;对于Linux服务器上托管.NET Core项目十分好奇。因为…