news 2026/5/12 21:56:41

【C++类与对象·中】对象生命周期:拷贝、析构与资源管理

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【C++类与对象·中】对象生命周期:拷贝、析构与资源管理

引言:

上一篇我们聊了类与对象的基础:封装、访问控制、构造函数初探。今天我们深入一步,聊聊对象从被创建、复制,到最终销毁整个生命周期中的关键机制。这个过程听起来抽象,但其实决定了你的程序是否稳定、是否内存安全。尤其当你开始管理动态内存(比如new/malloc)时,这些知识就是你程序的“安全带”。

当对象拥有动态资源(比如堆内存)时,如何安全地创建、复制、销毁它?一不小心,程序就会内存泄漏、双重释放,甚至直接崩溃!

这篇文章,将带你掌握对象生命周期的核心机制,关键内容:

  • 六大默认成员函数全景图
  • 构造函数的细节与陷阱
  • 析构函数如何成为资源清理的“守门人”
  • 拷贝构造 vs 赋值重载的本质区别
  • 运算符重载怎么写才规范
  • const成员函数与取地址重载的使用场景

准备好了吗?我们出发!

1、默认成员函数:编译器悄悄送你的“六件套”

即使你一个函数都不写,C++ 编译器也会为你的类自动生成6 个默认成员函数,它们是:

  1. 构造函数(Constructor)
  2. 析构函数(Destructor)
  3. 拷贝构造函数(Copy Constructor)
  4. 赋值运算符重载(Assignment Operator)
  5. 取地址运算符重载(普通版)
  6. 取地址运算符重载const版)

💡重点提醒: 前 4 个是核心!后两个极少需要自定义(除非你想“隐藏对象地址”,后面会讲)。 C++11 后还增加了移动构造移动赋值,我们后续再聊。

一句话比喻: 如果说类是一栋房子的设计图纸,对象就是建好的房子;构造函数是装修队,负责“布置好屋内”;析构函数是拆迁队,负责“清理干净垃圾”;拷贝构造则是“照着房子再建一栋一模一样的”。

学习默认成员函数,要思考两个问题

  1. 编译器自动生成的行为,是否满足我的需求
  2. 如果不满足,我该怎么自己实现

2. 构造函数:不只是“创建”,更是“初始化”

构造函数的主要任务不是分配空间(栈对象在函数调用时空间已分配),而是初始化对象的状态。它替代了 C 语言中手动调用Init()的繁琐流程。

✅ 构造函数的 7 个特性:
  1. 函数名与类名完全相同
  2. 无返回值(连void都不能写)
  3. 对象实例化时自动调用
  4. 可以重载
  5. 不写时,编译器自动生成无参默认构造函数;一旦你写了任何构造,编译器就不再生成
  6. 默认构造函数包含三类:
    • 无参构造
    • 全缺省构造(如Date(int y=1, int m=1, int d=1)
    • 编译器自动生成的构造 →三者只能存在一个!否则调用会歧义。
  7. 编译器生成的构造函数行为:
    • 内置类型int,char*等):不初始化(值随机!)
    • 自定义类型(如Stack):调用其默认构造函数
踩坑故事:Date d3();不是对象!

代码语言:javascript

AI代码解释

Date d1; // ✅ 调用默认构造 Date d2(2025,1,1); // ✅ 调用带参构造 Date d3(); // ❌ 这是函数声明!不是对象!

编译器会警告:warning C4930: "Date d3(void)": 未调用原型函数记住:无参构造创建对象,后面不要加括号!

默认构造函数的三种形式:
  1. 无参构造函数
  2. 全缺省构造函数
  3. 编译器自动生成的构造函数

⚠️注意:这三者只能存在一个!否则会调用歧义。

编译器生成的构造函数行为:
  • 内置类型(如int,char*):不初始化(值是随机的!)
  • 自定义类型(如Stack):调用其默认构造函数
代码演示Date类的多种构造方式

代码语言:javascript

AI代码解释

#include <iostream> using namespace std; class Date { public: // 1. 无参构造 Date() { _year = 1; _month = 1; _day = 1; } // 2. 带参构造 Date(int year, int month, int day) { _year = year; _month = month; _day = day; } // 3. 全缺省构造(与上面互斥,此处注释) // Date(int year = 1, int month = 1, int day = 1) { ... } void Print() { cout << _year << "/" << _month << "/" << _day << endl; } private: int _year, _month, _day; }; int main() { Date d1; // 调用默认构造 Date d2(2025, 1, 1); // 调用带参构造 d1.Print(); d2.Print(); // 注意:Date d3(); 不是对象!而是函数声明(经典坑) return 0; }

最佳实践:用全缺省构造,既能当默认构造用,又能接受参数,一举两得!

3. 析构函数:资源清理的“最后一道防线”

析构函数不负责销毁对象本身(栈对象随栈帧自动释放),而是负责清理对象持有的资源,比如动态分配的内存、打开的文件等。


www.dongchedi.com/article/7594896034183397912
www.dongchedi.com/article/7594896087656694334
www.dongchedi.com/article/7594914706423513662
www.dongchedi.com/article/7594915221282865689
www.dongchedi.com/article/7594913131445764633
www.dongchedi.com/article/7594913940153467416
www.dongchedi.com/article/7594913119710167614
www.dongchedi.com/article/7594912644462002712
www.dongchedi.com/article/7594913194427548222
www.dongchedi.com/article/7594913400799560254
www.dongchedi.com/article/7594909709942243865
www.dongchedi.com/article/7594910416170484248
www.dongchedi.com/article/7594908118182658622
www.dongchedi.com/article/7594910049232110104
www.dongchedi.com/article/7594907960862949913
www.dongchedi.com/article/7594908188798075417
www.dongchedi.com/article/7594907774480712217
www.dongchedi.com/article/7594907222254567998
www.dongchedi.com/article/7594906290414387737
www.dongchedi.com/article/7594905054898242073
www.dongchedi.com/article/7594904442156237337
www.dongchedi.com/article/7594906050713829950
www.dongchedi.com/article/7594902352139190846
www.dongchedi.com/article/7594900815396323865
www.dongchedi.com/article/7594900774837273113
www.dongchedi.com/article/7594899434665034265
www.dongchedi.com/article/7594899719034667544
www.dongchedi.com/article/7594900424902099480
www.dongchedi.com/article/7594897374330438169
www.dongchedi.com/article/7594897204683604542
www.dongchedi.com/article/7594897178171425305
www.dongchedi.com/article/7594897768821588505
www.dongchedi.com/article/7594897245074752062
www.dongchedi.com/article/7594896185186320921
www.dongchedi.com/article/7594895353548669465
www.dongchedi.com/article/7594897151948718616
www.dongchedi.com/article/7594896358880854553
www.dongchedi.com/article/7594895416219599384
www.dongchedi.com/article/7594893807196455449
www.dongchedi.com/article/7594895049499034137
www.dongchedi.com/article/7594893585233855000
www.dongchedi.com/article/7594894559332418072

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/11 12:43:29

DLSS Swapper终极教程:如何轻松管理游戏DLSS版本提升性能?

DLSS Swapper终极教程&#xff1a;如何轻松管理游戏DLSS版本提升性能&#xff1f; 【免费下载链接】dlss-swapper 项目地址: https://gitcode.com/GitHub_Trending/dl/dlss-swapper 还在为游戏卡顿而烦恼吗&#xff1f;想要在不同DLSS版本间自由切换却不知从何下手&…

作者头像 李华
网站建设 2026/5/11 3:41:20

DLSS Swapper完整使用教程:如何轻松管理游戏DLSS版本提升性能

DLSS Swapper完整使用教程&#xff1a;如何轻松管理游戏DLSS版本提升性能 【免费下载链接】dlss-swapper 项目地址: https://gitcode.com/GitHub_Trending/dl/dlss-swapper 还在为游戏卡顿和画质问题烦恼吗&#xff1f;想要自由切换不同DLSS版本却不知从何下手&#xf…

作者头像 李华
网站建设 2026/5/12 5:16:15

Proteus使用教程:C51代码烧录与联合验证

用Proteus玩转C51&#xff1a;零硬件也能高效仿真调试你有没有过这样的经历&#xff1f;写完一段单片机代码&#xff0c;满心期待地烧进开发板&#xff0c;结果LED不亮、串口乱码、按键无响应……反复插拔下载器&#xff0c;查线路、换芯片&#xff0c;折腾半天才发现是晶振频率…

作者头像 李华
网站建设 2026/5/12 7:23:21

2020 年 6 月青少年软编等考 C 语言三级真题解析

目录 T1. 最接近的分数 思路分析 T2. 和数 思路分析 T3. 吃糖果 思路分析 T4. 汉诺塔问题 思路分析 T5. 文件结构 “图” 思路分析 T1. 最接近的分数 题目链接:SOJ D1267 分母不超过 N N N 且小于 A / B A/B A/B

作者头像 李华
网站建设 2026/5/12 18:05:15

DLSS Swapper终极指南:轻松解决游戏DLSS兼容性问题

DLSS Swapper终极指南&#xff1a;轻松解决游戏DLSS兼容性问题 【免费下载链接】dlss-swapper 项目地址: https://gitcode.com/GitHub_Trending/dl/dlss-swapper &#x1f3ae; 你是否遇到过这样的情况&#xff1a;心爱的游戏更新后&#xff0c;DLSS效果反而变差&#…

作者头像 李华
网站建设 2026/5/8 4:49:39

DLSS Swapper终极指南:三步解锁游戏性能新高度

DLSS Swapper终极指南&#xff1a;三步解锁游戏性能新高度 【免费下载链接】dlss-swapper 项目地址: https://gitcode.com/GitHub_Trending/dl/dlss-swapper 还在为游戏卡顿、画质模糊而烦恼吗&#xff1f;想不花一分钱就让老旧游戏焕发新生&#xff1f;DLSS Swapper就…

作者头像 李华