当前位置: 首页 > news >正文

C++超详细讲解构造函数与析构函数的用法及实现

写在前面

上一节解决了类与对象封装的问题,这一节就是对象的初始化和清理的构造函数与析构函数的内容了;对象的初始化和清理也是两个非常重要的安全问题:一个对象或者变量没有初始状态,对其使用后果是未知,同样的使用完一个对象或变量,没有及时清理,也会造成一定的安全问题;c++利用了构造函数和析构函数解决上述问题,这两个函数将会被编译器自动调用,完成对象初始化和清理工作。对象的初始化和清理工作是编译器强制要我们做的事情,因此如果我们不提供构造和析构,编译器提供编译器提供的构造函数和析构函数是空实现。下面开始正文:

构造函数和析构函数

语法

构造函数语法: 类名(){}

1、没有返回值也不写void

2、函数名称与类名相同

3、构造函数可以有参数,因此可以发生重载

4、程序在调用对象时会自动调用,无需手动调用且只会调用一次

析造函数语法: ~类名(){}

1、没有返回值也不写void

2、函数名称与类名相同,在名称前加上符号~

3、构造函数不可以有参数,因此不可以发生重载

4、程序在对象销毁前会自动调用析构,无需手动调用且只会调用一次

作用

构造函数 主要作用于创建对象时为对象的成员属性赋值,构造函数由编译器自动调用,无须手动调用

析构函数 主要作用于对象销毁前系统自动调用,执行一些清理工作

代码实现

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

#include<iostream>

usingnamespacestd;

classPerson

{

public:

Person()

{

cout <<"Person构造函数的调用"<< endl;

}

~Person()

{

cout <<"~Person析构函数的调用"<< endl;

}

};

voidtest01()

{

Person p;//栈上的对象运行完毕后,编译器自动释放

}

intmain()

{

test01();

}

test01中创建了Person类p,主函数只是调用了一下创建的Person类p,编译器就自动调用了类的构造函数和析构函数,析构函数是程序运行完毕后,编译器自动清理内存空间的时候调用的。

两大分类方式

按参数分为 有参构造 和 无参构造

按类型分为 普通构造 和 拷贝构造

无参和有参构造很好理解,就是有无参数的区别,这里讲一下拷贝构造函数:

1

2

3

4

5

6

7

//拷贝构造函数

Person(constPerson &p)//格式: const 类名 引用(&)变量名

{

//讲传入的人身上的所有属性,拷贝到我身上

age = p.age;

cout <<"Person的拷贝构造函数调用"<< endl;

}

Person()的括号中是const Person &p,这是拷贝构造的函数格式,他需要传入相同类的对象,会产生一个具有相同属性的类,比如p1的年龄为20,经过拷贝构造p2的年龄也会是20,但是两个类对象的地址并不相同,这个到后面会具体解释

三种调用方式

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

classPerson

{

public:

//构造函数

Person()

{

cout <<"Person的无参构造函数调用"<< endl;

}

Person(inta)

{

age = a;

cout <<"Person的有参构造函数调用"<< endl;

}

//拷贝构造函数

Person(constPerson &p)//格式: const 类名 引用(&)变量名

{

//讲传入的人身上的所有属性,拷贝到我身上

age = p.age;

cout <<"Person的拷贝构造函数调用"<< endl;

}

~Person()

{

cout <<"~Person的析构函数调用"<< endl;

}

intage;

};

括号法

1

2

3

4

5

Person p;//默认构造函数调用

Person p2(10);//有参构造函数

Person p3(p2);//拷贝构造函数

cout <<"p2 age="<< p2.age << endl;

cout <<"p3 age="<< p3.age << endl;

注意事项:调用默认构造函数的时候,不要加();Person p1() 编译器会认为是函数的声明,不认为在创建对象,等同于 void func()

显示法

1

2

3

4

5

Person p;

Person p2=Person(10);//有参构造函数

Person p3=Person(p2);//拷贝构造函数

Person(100);//匿名对象,特点:当前执行完毕后,系统会立即回收掉匿名对象

cout <<"AAAAA"<< endl;

注意事项2:拷贝构造初始化匿名对象等同于去掉括号,导致重定义,不要用拷贝构造初始化匿名对象,如果利用匿名对象的话,会和Peron p2=Person(10),重复,出现重定义错误;也不要用拷贝构造初始化匿名对象。

隐式转换法

1

2

Person p2 = 10;// 有参构造函数

Person p3 = p2;// 拷贝构造函数

这个方法不推荐使用,调用的很不明显,建议使用前面两个方法调用构造函数。

正确调用拷贝构造函数

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

classPerson

{

public:

Person()

{

cout <<"Person的无参构造函数调用"<< endl;

}

Person(inta)

{

m_age = a;

cout <<"Person的有参构造函数调用"<< endl;

}

Person(constPerson& p)

{

m_age = p.m_age;

cout <<"Person的拷贝构造函数调用"<< endl;

}

~Person()

{

cout <<"Person 的析构函数调用"<< endl;

}

intm_age;

};

正常调用

1

2

3

4

5

6

voidtest01()

{

Person p1(20);

Person p2(p1);

cout <<"p2的年龄为:"<< p2.m_age << endl;

}

主函数中直接调用test01,这时候会显示 p2的年龄为20,并且打印:拷贝构造函数的调用。所以说,使用一个已经创建完毕的对象来初始化一个新对象的时候会调用拷贝构造函数

值传递的方式给函数参数传值

1

2

3

4

5

6

7

voiddoWork(Person p)

{ }

voidtest02()

{

Person p;

doWork(p);

}

大家可以猜一下,在主函数调用,会运行出什么结果,答案是:无参构造函数调用和拷贝构造函数调用,最后是两个析构函数调用;浅析一下过程,调用test02时创建了对象P,所以自动调用无参构造函数,当运行到doWork(p)时,调用拷贝构造函数,随后拷贝构造函数被清理,调用析构函数,程序结束前,p被清理,再次调用析构函数,程序结束。

http://www.jsqmd.com/news/909614/

相关文章:

  • 武汉寄快递怎么选?2026 全国靠谱寄件平台全攻略,不同场景精准匹配 - 时讯资讯
  • 微信聊天记录永久保存的终极指南:三步实现完整数据备份
  • DIY铝箔带式高音单元:从电磁原理到动手制作的完整指南
  • 如何构建个人数字记忆保险箱:微信聊天记录终极管理方案
  • 2026年Q2安徽物资回收优质厂家首选推荐:合肥越纪物资回收有限公司18326124448 - 安互工业信息
  • 从原理图到PCB:电路设计与制作全流程实战指南
  • 一篇文章带你了解C++模板编程详解
  • 2026年苏州本地窗户漏水维修服务机构3家核心能力专业深度解析 专业防水公司排名推荐(2026年5月防水补漏最新TOP权威排名) - 鼎壹万修缮说
  • 5分钟搞定OBS RTSP直播:obs-rtspserver插件完整指南
  • 如何快速掌握BepInEx:面向游戏爱好者的终极插件框架指南
  • 2026年比话降AI率实测报告:知网论文AI率84.9%降到1.4%
  • 如何通过Raw Accel鼠标加速驱动优化游戏性能:7种曲线类型完全指南
  • 甘肃省嘉峪关CPPMSCMP官网报考入口,官方授权双证报考中心 - 众智商学院课程中心
  • Cadence OrCAD 16.6导出网表时,搞定那个烦人的“tmp_pstxnet.dat”写入错误
  • AI时代营销变革:从效率工具到人机共生的艺术
  • 从TLS 1.3到区块链:一文搞懂ECDSA和ECDH在现代安全协议里的核心作用
  • Harbor离线安装后,你的Docker客户端真的配好了吗?一份保姆级的证书配置与验证清单
  • 2026 年 5 月执业医师备考工具实测:破解刷题痛点的高效选择★★★★★ - 讲清楚了
  • DIY高性能触觉反馈鼠标:基于光标检测的30毫秒响应方案
  • Arduino土壤湿度监测仪DIY:从传感器原理到智能灌溉实践
  • React技术周刊 2026年第18周
  • 甘肃省临夏CPPMSCMP官网报考入口,官方授权双证报考中心 - 众智商学院课程中心
  • CoolProp:热物理计算领域的高性能开源架构深度解析
  • 零编程基础也能掌握的KH Coder:13种语言文本挖掘终极指南
  • 甘肃省平凉CPPMSCMP官网报考入口,官方授权双证报考中心 - 众智商学院课程中心
  • 长期使用 Taotoken 的 Token 计费模式让每笔支出都清晰可查
  • 在Dusun DSGW-210物联网网关部署Home Assistant全攻略
  • 2026重庆速洁家政:渝中口碑好的大学城家政公司 - LYL仔仔
  • Arduino LED测试仪制作:一键测量正向电压与限流电阻计算
  • 云学习笔记|基于Java+vue的云的学习笔记系统(源码+数据库+文档)