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

C++基础笔记(7):拷贝构造函数

在 C++ 面向对象编程中,构造函数负责对象的创建,而拷贝构造函数则专门处理对象的“复制式创建”。当我们使用已有对象去初始化一个新对象,或者在函数参数传递与返回对象时发生值传递时,拷贝构造函数就会被自动调用。它本质上是一种特殊的构造函数,用于保证新对象能够正确地复制原对象的状态与资源,而不是简单地进行位级复制。

1. 基本概念

拷贝构造函数(Copy Constructor)是一种特殊的构造函数,它用于使用一个已有对象来初始化同类型的新对象。与普通构造函数不同,拷贝构造函数的参数是该类对象本身的引用,其主要作用是完成对象状态的复制,使新对象在创建时就拥有与原对象相同的数据内容。拷贝构造函数通常用于:

  • 通过使用另一个同类型的对象来初始化新创建的对象。
  • 复制对象把它作为参数传递给函数。
  • 复制对象,并从函数返回这个对象。

如果在类中没有定义拷贝构造函数,编译器会自行定义一个。如果类带有指针变量,并有动态内存分配,则它必须有一个拷贝构造函数。拷贝构造函数的最常见形式如下:

classname (const classname &obj) { // 构造函数的主体 }

其中参数通常使用const引用,这是因为:一方面避免产生新的临时对象(否则会递归调用拷贝构造函数),另一方面保证原对象不会被修改。下面的示例展示了按值传递对象时自动触发拷贝构造函数的情况:

#include <iostream> using namespace std; class Demo { public: Demo() { cout << "默认构造函数\n"; } Demo(const Demo& d) { cout << "拷贝构造函数\n"; } }; void func(Demo d) // 按值传参 { cout << "进入函数\n"; } int main() { Demo d1; func(d1); // 传值调用,产生临时对象,触发拷贝构造 }

在调用func(d1)时,编译器会先创建一个临时对象d,用d1初始化它,因此拷贝构造函数被调用一次。类似地,当函数返回对象时也会发生同样的复制过程(尽管现代编译器常通过返回值优化 RVO 省略拷贝)。

2. 浅拷贝与深拷贝

拷贝构造函数可以通过对象复制的两种实现方式:浅拷贝(Shallow Copy)与深拷贝(Deep Copy)进行分类。它们的核心区别在于是否复制对象所拥有的资源本身

2.1. 浅拷贝

浅拷贝是一种最简单的对象复制方式。 默认生成的拷贝构造函数和拷贝赋值运算符通常采用的就是浅拷贝策略 。这种方式在对象不涉及资源管理时是安全且高效的,但在涉及动态内存时会带来隐患。浅拷贝的特点在于:

  • 仅复制成员变量的值,而不复制成员变量所指向的资源本身。
  • 若对象内部包含指针,那么复制后多个对象将指向同一块内存区域,资源被共享。

下面示例演示浅拷贝的行为:

#include <iostream> using namespace std; class ShallowCopy { public: int* data; ShallowCopy(int value) { data = new int(value); } // 浅拷贝构造函数 ShallowCopy(const ShallowCopy& other) { data = other.data; // 仅复制指针地址 } ~ShallowCopy() { delete data; } }; int main() { ShallowCopy a(10); ShallowCopy b = a; // 浅拷贝 cout << *a.data << " " << *b.data << endl; }

在这个例子中,abdata指针指向同一块内存。当其中一个对象析构释放资源后,另一个对象仍然持有该地址,再次释放时就会产生未定义行为。这正是浅拷贝最大的问题:资源共享导致生命周期冲突

2.2. 深拷贝

深拷贝则是在复制对象时,不仅复制成员变量的值,还会复制对象所拥有的资源本身,为新对象创建一份独立的资源副本。这样每个对象都拥有自己的数据,不会互相影响,从而保证资源管理的安全性。

对于包含指针或动态内存的类,通常需要手动实现深拷贝,否则默认拷贝可能造成严重错误。下面示例展示深拷贝的实现方式:

#include <iostream> using namespace std; class DeepCopy { public: int* data; DeepCopy(int value) { data = new int(value); } // 深拷贝构造函数 DeepCopy(const DeepCopy& other) { data = new int(*(other.data)); // 创建新的内存副本 } ~DeepCopy() { delete data; } }; int main() { DeepCopy a(20); DeepCopy b = a; // 深拷贝 cout << *a.data << " " << *b.data << endl; }

在深拷贝中,abdata指向不同的内存地址,即使其中一个对象被销毁,另一个对象仍然保持有效。这种方式确保了对象之间的数据独立性,是处理动态资源类时的标准做法。

2.3. 深拷贝与浅拷贝的关键区别

从本质上看,浅拷贝与深拷贝的区别在于资源是否独立。

  • 浅拷贝复制的是“指向资源的地址”,而深拷贝复制的是“资源本身”。因此,浅拷贝实现简单、效率高,但可能引发资源冲突;
  • 深拷贝实现复杂,需要额外的内存分配与释放,但安全可靠 。

如果类涉及动态内存、文件、网络连接或其他独占资源,通常必须实现深拷贝,并同时提供正确的拷贝赋值运算符和析构函数,以保证资源生命周期管理的一致性。

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

相关文章:

  • 函数式编程的架构目标
  • 2026SAT精品小班辅导机构怎么选?高分备考优质SAT小班机构测评 - 品牌2026
  • 纯手工搭建:基于Matlab/Simulink的增程式混合动力汽车建模仿真模型教程
  • 【笔记】用cursor手搓cursor(三)简单尝试claude code
  • 开发者效率周刊 #01
  • 基于 Matlab 的球轴承拟静力学计算:探索不同参数下的生热量
  • 2026年3月广州装饰装修公司选择指南:办公室装修,厂房装修,商铺装修,酒店装修,会所装修,林迪装饰深耕工装领域的专业服务提供商 - 海棠依旧大
  • 2026年四川免砸砖维修厂家哪家强 精准找漏长效修复适配多场景需求 - 深度智识库
  • RVC语音转换精度评测:MOS分对比、频谱图相似度、F0曲线拟合效果
  • 西门子1500PLC饮料罐装线:从代码到螺丝刀的全栈开发实录
  • 大车相撞事故道路交通事故快速勘查系统厂商哪家好?安全高效优先 - 品牌2026
  • Ubuntu 安装完成后网络配置教程
  • DMXAPI 下的 PostgreSQL MCP Tool 使用笔记:少一点幻想,多一点可审计的能力
  • Gemini 3 Pro在学术写作中的全流程应用
  • Jmeter 内置的 python 版本
  • Git-RSCLIP在嵌入式系统中的应用:基于STM32的轻量级部署
  • 2026年3月山东护栏厂家选择指南:不锈钢复合管,不锈钢栏杆,护栏,桥梁护栏,河道护栏,山东绿洲护栏深耕行业的专业护栏服务商 - 海棠依旧大
  • 别再只调电位器了!用Arduino+光耦MOC3061玩转双向可控硅的零位控制(附完整代码)
  • OpenClaw学术伦理应用:Qwen3-32B本地化处理心理学实验数据
  • 基于Matlab的Tamura纹理特征提取
  • 灰狼算法优化的LSSVR程序
  • AT_arc216_c [ARC216C] Count Power of 2
  • UI/UX 设计原则:从美学到体验的完美融合
  • 磁力搜索终极指南:10分钟掌握开源聚合搜索工具magnetW
  • 2026年泉州榻榻米定制厂家推荐:衣帽间定制/橱柜定制/衣柜定制/玄关柜定制/酒柜定制一站式服务商精选 - 品牌推荐官
  • Nginx 抢跑导致的 Docker 服务“全线雪崩
  • 24小时响应+全流程托管:甘肃殡葬服务“一站式”标杆的实力答卷 - 深度智识库
  • 累加和校验算法原理与嵌入式应用
  • 改进下垂控制的孤岛型并联分布式电源微电网系统
  • F - Grid Clipping