C++:3.构造、拷贝构造、赋值重载与资源管理 一、复习析构函数不同对象的析构时机栈对象出函数作用域 } 时自动析构全局对象程序运行结束时析构堆对象手动调用delete 时析构this指针类的普通成员方法编译器编译后都会增加一个形参变量 类类型 *this对象调用方法的时候实际上调用的是全局方法把对象的地址作为实参传入this指针接收成员方法里面访问的成员变量或者其它的成员方法前面默认都会加上this-一个类定义的很多对象每个对象都有自己的成员变量但是共享一套成员方法在成员方法里面有个this指针形参变量专门指向调用该方法的对象读写该对象的成员变量二、 C类深度剖析构造、拷贝构造、赋值重载与资源管理一、C类四大默认函数概览当你一个都不写编译器会隐式生成默认构造拷贝构造函数赋值运算符重载 operator析构函数默认版本全部为浅拷贝只要类管理堆资源必须自己实现深拷贝。基础类框架#includeiostream#includecstringusingnamespacestd;classPerson{public:// 默认构造Person(){coutcall Person() | this thisendl;namenullptr;}// 有参构造Person(constchar*name,intage,charsex){coutcall Person(const char*, int, char) | this thisendl;this-namenewchar[strlen(name)1];strcpy(this-name,name);this-ageage;this-sexsex;}// 拷贝构造函数深拷贝实现Person(constPersonrhs){coutcall Person(const Person rhs) 源:rhs - 新对象:thisendl;// 重新开辟堆内存复制内容深拷贝核心this-namenewchar[strlen(rhs.name)1];strcpy(this-name,rhs.name);this-agerhs.age;this-sexrhs.sex;}// 赋值运算符重载深拷贝Personoperator(constPersonrhs){coutcall operator(const Person rhs) 源:rhs 当前对象:thisendl;// 1. 防止自赋值 per1 per1;if(thisrhs){return*this;}// 2. 释放当前对象旧堆资源避免内存泄漏delete[]this-name;// 3. 分配新内存拷贝数据this-namenewchar[strlen(rhs.name)1];strcpy(this-name,rhs.name);this-agerhs.age;this-sexrhs.sex;// 返回*this支持链式赋值 abcreturn*this;}// 析构函数~Person(){coutcall ~Person() | this thisendl;delete[]name;namenullptr;}constchar*getName(){returnname;}intgetAge(){returnage;}chargetSex(){returnsex;}voidshow(){cout姓名:name 年龄:age 性别:(sexM?男:女)endl;}private:char*name;intage;charsex;};二、拷贝构造函数1. 触发时机只有新建对象初始化时调用intmain(){Personper1(赵云,23,M);// 方式1Personper2(per1);// 方式2Person per3per1;per2.show();per3.show();return0;}✅ 关键点Person per obj创建对象阶段 → 拷贝构造❌ 不要混淆Person a;aper1;// a早已创建这里不会调用拷贝构造调用赋值重载2. 浅拷贝问题说明编译器默认版本等价于Person(constPersonrhs){this-namerhs.name;// 只复制指针地址浅拷贝this-agerhs.age;this-sexrhs.sex;}两个对象name指向同一块堆内存析构时delete[]两次 → 程序崩溃。三、赋值运算符重载 operator1. 使用示例代码intmain(){Personper1(赵云,23,M);Person per4;// per4已经构造完成per4per1;// 调用 operatorper4.show();per1per1;// 测试自赋值防护Person per5;per5Person(张飞,25,M);// 临时对象赋值return0;}2. 必须遵守三条规范判断自赋值this rhs先释放自身旧资源返回*this引用✔ 一句话区分拷贝构造 / 赋值重载拷贝构造对象还不存在正在创建初始化赋值重载对象已经存在覆盖原有内容四、函数返回局部对象RVO返回值优化案例重点完整待测代码PersonGetPerson(Personper){constchar*nameper.getName();intageper.getAge();charsexper.getSex();PersontmpPer(name,age,sex);// 栈上局部对象returntmpPer;}intmain(){Personper1(赵云,23,M);Person per2GetPerson(per1);per2.show();return0;}4.1 不开启编译器优化理论标准流程Person per1(赵云,23,M);调用三参数有参构造函数创建per1。进入GetPerson函数内部Person tmpPer(name, age, sex);调用三参数有参构造在函数栈上创建局部对象tmpPer。return tmpPer;使用tmpPer拷贝构造临时对象函数返回值临时对象。函数作用域结束局部对象tmpPer销毁调用析构函数。Person per2 GetPerson(per1);用返回的临时对象拷贝构造per2对象。临时对象生命周期结束调用析构函数销毁临时对象。main函数结束per2析构、per1析构各调用一次析构。无优化完整调用顺序三参构造(per1) → 三参构造(tmpPer) → 拷贝构造(临时返回对象) → 析构(tmpPer) → 拷贝构造(per2) → 析构(临时对象) → 析构(per2) → 析构(per1)4.2 开启RVO返回值优化编译器默认开启实际运行现象RVO返回局部对象时编译器把局部对象的内存直接构造到外部接收对象per2的内存空间省去两次拷贝构造、省去一次局部tmpPer析构。实际调用顺序Person per1(赵云, 23, M);→三参数有参构造 per1GetPerson内部直接在per2的内存上执行构造逻辑 →三参数有参构造 per2main结束依次析构 per2、per1。实际运行只会看到两次三参构造两次析构看不到拷贝构造执行。4.3 两种写法对比//写法1创建局部对象再returnPersontmpPer(name,age,sex);returntmpPer;//写法2return 匿名临时对象returnPerson(name,age,sex);第二种属于NRVO同样会被编译器优化不会产生多余拷贝。4.4 区分两种接收返回值写法//写法A对象初始化Person per2 GetPerson(per1);// 接收返回值对象正在创建走拷贝构造会被RVO优化掉Person per2GetPerson(per1);//写法B先定义对象再赋值Person per2;per2GetPerson(per1);写法Aper2是新建对象理论上触发拷贝构造RVO优化后直接构造。写法Bper2已经通过默认构造函数创建完成GetPerson返回临时对象调用赋值运算符重载把临时对象赋值给per2函数结束临时对象调用析构销毁。写法B调用顺序三参构造(per1) → 默认构造(per2) → 三参构造(tmpPer) →拷贝构造(返回临时) →析构(tmpPer) → operator(per2 临时对象) →析构(返回临时) →main结束析构per2、per1。重点面试Person per2 GetPerson(per1);不是赋值是对象初始化per2 GetPerson(per1);才是赋值重载调用。五、explicit 关键字详解5.1 隐式转换问题给类增加单参数构造classTest{public:Test(intage){cout构造 age ageendl;}};intmain(){Test t20;// 不写explicit时合法隐式转换Test temp(20); Test t temp;return0;}很多时候这种自动转换是意外bug。5.2 explicit 禁止隐式转换classTest{public:explicitTest(intage){cout构造 age ageendl;}};intmain(){// Test t 20; // 编译报错禁止隐式转换Testt(20);// ✅ 显式调用允许return0;}使用小结只修饰构造函数多用于单参数构造阻止编译器自动发生隐式类型转换C开发建议单参数构造默认加上explicit六、核心总结管理堆内存的类必须手写拷贝构造 operator 析构三法则浅拷贝 复制指针深拷贝 重新开辟内存复制数据Person obj other≠obj other前者拷贝构造后者赋值重载赋值函数务必处理自赋值explicit杜绝构造函数意外隐式转换函数返回局部对象标准流程会触发拷贝构造现代编译器RVO/NRVO优化会消除多余拷贝接收函数返回值Person p func();对象初始化理论拷贝构造p func();对象已存在调用赋值运算符重载。拓展关闭RVO优化gcc参数-fno-elide-constructors可以看到没有优化的完整调用流程方便学习调试。

相关新闻

最新新闻

复现AMD官方基准:Kimi-K2.5-Eagle3-FP8的vllm bench serve吞吐测试完整教程

复现AMD官方基准:Kimi-K2.5-Eagle3-FP8的vllm bench serve吞吐测试完整教程

复现AMD官方基准:Kimi-K2.5-Eagle3-FP8的vllm bench serve吞吐测试完整教程 【免费下载链接】Kimi-K2.5-Eagle3-FP8 项目地址: https://ai.gitcode.com/hf_mirrors/amd/Kimi-K2.5-Eagle3-FP8 想亲手复现 AMD 官方公布的 Kimi-K2.5-Eagle3-FP8 吞吐测试结果吗…

2026/8/17 22:36:58
CTF 比赛入门科普:什么是 CTF?考什么?需要掌握哪些技术?

CTF 比赛入门科普:什么是 CTF?考什么?需要掌握哪些技术?

在网络安全领域,CTF(Capture The Flag,夺旗赛)是检验技术实力的 “试金石”,也是白帽黑客成长的 “练兵场”。对于刚接触网络安全的新手来说,CTF 既神秘又充满吸引力 —— 它不像传统考试那样侧重理论&…

2026/8/17 22:36:58
零基础打造专属情侣互动小程序:从异地恋到甜蜜日常的完整玩法指南

零基础打造专属情侣互动小程序:从异地恋到甜蜜日常的完整玩法指南

零基础打造专属情侣互动小程序:从异地恋到甜蜜日常的完整玩法指南 【免费下载链接】Rainbow-Cats-Personal-WeChat-MiniProgram 给女朋友做的微信小程序!情侣自己的任务和商城系统! 项目地址: https://gitcode.com/gh_mirrors/ra/Rainbow-C…

2026/8/17 22:36:58
WorkshopDL 免费模组下载完整指南:没有 Steam 客户端,也能一键拿到创意工坊的模组

WorkshopDL 免费模组下载完整指南:没有 Steam 客户端,也能一键拿到创意工坊的模组

WorkshopDL 免费模组下载完整指南:没有 Steam 客户端,也能一键拿到创意工坊的模组 【免费下载链接】WorkshopDL WorkshopDL - The Best Steam Workshop Downloader 项目地址: https://gitcode.com/gh_mirrors/wo/WorkshopDL 你刚在 Epic 打折时入…

2026/8/17 22:36:58
新手如何开启漏洞挖掘?路线规划 + 靶场练习 + 赏金平台完整解析

新手如何开启漏洞挖掘?路线规划 + 靶场练习 + 赏金平台完整解析

小白漏洞挖掘入门指南:零基础学习路线、靶场实操、赏金平台讲解 学会这一招,你的第一个漏洞可能就在今晚! 一、前言:别再被“漏洞挖掘”四个字吓到了! “漏洞挖掘”、“渗透测试”、“安全研究员”……这些词听起来是不…

2026/8/17 22:36:58
免费跨平台MEGA下载器MegaBasterd实测:如何告别限速,一键下完大文件

免费跨平台MEGA下载器MegaBasterd实测:如何告别限速,一键下完大文件

免费跨平台MEGA下载器MegaBasterd实测:如何告别限速,一键下完大文件 【免费下载链接】megabasterd Yet another unofficial (and ugly) cross-platform MEGA downloader/uploader/streaming suite. 项目地址: https://gitcode.com/gh_mirrors/me/megab…

2026/8/17 22:31:58