【C++指南】类和对象(四):类的默认成员函数——全面剖析 : 拷贝构造函数

news2024/11/25 20:18:49

 引言

拷贝构造函数是C++中一个重要的特性,它允许一个对象通过另一个已创建好的同类型对象来初始化

了解拷贝构造函数的概念、作用、特点、规则、默认行为以及如何自定义实现,对于编写健壮和高效的C++程序至关重要。

 C++类和对象系列文章,可点击下方链接阅读:

【C++指南】类和对象(一):类和对象的定义和使用 基础讲解_c++ 类对象的使用-CSDN博客

【C++指南】类和对象(二):类的默认成员函数——全面剖析 :构造函数-CSDN博客

【C++指南】类和对象(三):类的默认成员函数——全面剖析: 析构函数-CSDN博客

【C++指南】类和对象(四):类的默认成员函数——全面剖析 拷贝构造函数-CSDN博客

【C++指南】类和对象(五):类的默认成员函数——全面剖析 赋值运算符重载函数-CSDN博客

目录

引言

🍃概念

🍃作用

🍃特点

触发拷贝函数自动调用的情况:

🍃规则

🍃默认拷贝构造函数的行为

🍃自定义实现拷贝构造函数

🍃总结


🍃概念

如果⼀个构造函数的第⼀个参数是自身类类型的引用,且任何额外的参数都有默认值,则此构造函数 也叫做拷贝构造函数。

拷贝构造函数是一种特殊的构造函数,它接受一个同类型的对象的引用作为参数,用于初始化新创建的对象。

拷贝构造函数的声明通常如下:

ClassName(const ClassName& other);
其中,ClassName是类的名字,other 是传入的对象。 

🍃作用

拷贝构造函数的主要作用是实现对象的深拷贝或浅拷贝

  • 深拷贝:在内存中为对象分配新的空间,并复制源对象的所有成员(包括动态分配的内存)。
  • 浅拷贝:仅复制对象的成员值,如果成员包含指针,则两个对象将共享相同的内存地址。

关于浅拷贝与深拷贝的详细内容可以参考文章:

【C++指南】C++中的浅拷贝与深拷贝:深入剖析-CSDN博客 

🍃特点

  • 自动调用:在对象通过另一个对象初始化时,拷贝构造函数会被自动调用。
  • 参数传递:拷贝构造函数的参数是常量引用(const ClassName&),避免不必要的拷贝,同时防止对象在拷贝过程中被修改。

拷贝构造函数的参数必须是类类型对象的引用,而不是传值方式。主要是因为:

避免无限递归

如果拷贝构造函数的参数是传值方式,那么在调用拷贝构造函数时,编译器会尝试创建一个临时对象来传递给该函数。这个临时对象的创建又会调用拷贝构造函数,从而导致无限递归。最终,这会导致栈溢出和编译错误。

触发拷贝函数自动调用的情况:

1.对象初始化

  • 使用另一个同类型的对象来初始化一个新对象时。
MyClass obj1;  
MyClass obj2 = obj1;  // 调用拷贝构造函数

 2.函数参数传递

  • 当一个对象作为值参数传递给函数时。
void func(MyClass obj) {  
    // 在这里,obj是通过拷贝构造函数创建的  
}  
MyClass obj1;  
func(obj1);  // 调用拷贝构造函数

3.函数返回值

  • 当一个函数返回一个对象(作为值)时,会调用拷贝构造函数来构造返回的对象。
MyClass func() {  
    MyClass obj;  
    return obj;  // 调用拷贝构造函数  
}

4.编译器生成的临时对象

  • 编译器在某些情况下会生成临时对象,例如,在表达式中计算中间结果时。
MyClass obj = MyClass();  // 这里的`MyClass()`创建了一个临时对象,然后调用拷贝构造函数赋值给obj

🍃规则

  • 如果类中没有显式定义拷贝构造函数,编译器会提供一个默认的拷贝构造函数。
  • 拷贝构造函数不能被声明为const,因为它需要修改(初始化)目标对象。
  • 拷贝构造函数必须是可访问的,以便在需要时能够被调用。

🍃默认拷贝构造函数的行为

默认拷贝构造函数的行为是逐成员复制,对于基本类型成员,直接复制值,也就是浅拷贝对于对象成员,调用其拷贝构造函数

这种默认行为通常适用于不包含动态分配内存或资源管理(如文件句柄、网络连接等)的简单类。

🍃自定义实现拷贝构造函数

当类包含动态分配的内存、指针或需要管理的资源时,必须自定义拷贝构造函数来实现深拷贝,以避免浅拷贝带来的问题(如重复释放内存、数据不一致等)。

Tips:

如果⼀个类显式实现了析构并释放资源,那么他就 需要显式写拷贝构造,否则就不需要

以下是一个包含动态分配内存的类的示例,展示如何自定义拷贝构造函数:

#include <iostream>  
#include <cstring>  
  
class MyClass {  
private:  
    char* data;  
  
public:  
    // 默认构造函数  
    MyClass(const char* str = "") {  
        data = new char[strlen(str) + 1];  
        strcpy(data, str);  
    }  
  
    // 拷贝构造函数  
    MyClass(const MyClass& other) {  
        data = new char[strlen(other.data) + 1];  
        strcpy(data, other.data);  
    }  
  
    // 析构函数  
    ~MyClass() {  
        delete[] data;  
    }  
  
    // 打印数据  
    void print() const {  
        std::cout << data << std::endl;  
    }  
};  
  
int main() {  
    MyClass obj1("Hello");  
    MyClass obj2 = obj1; // 调用拷贝构造函数  
  
    obj1.print(); // 输出: Hello  
    obj2.print(); // 输出: Hello  
  
    return 0;  
}
在这个例子中,MyClass 包含一个指向字符数组的指针。自定义拷贝构造函数通过分配新的内存并复制字符串内容,实现了深拷贝。析构函数负责释放动态分配的内存,防止内存泄漏。

🍃总结

  • 拷贝构造函数是C++中用于通过另一个对象初始化新对象的特殊构造函数。
  • 它接受一个同类型的常量引用作为参数。
  • 如果没有显式定义,编译器会提供一个默认的拷贝构造函数,逐成员复制对象。
  • 自定义拷贝构造函数通常用于实现深拷贝,以避免浅拷贝带来的问题。
  • 编写拷贝构造函数时,需要特别注意动态分配的内存和需要管理的资源,确保正确复制和释放。

通过理解和应用拷贝构造函数,可以编写出更加健壮和高效的C++程序。

 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【计网】理解TCP全连接队列与tcpdump抓包

希望是火&#xff0c;失望是烟&#xff0c; 生活就是一边点火&#xff0c;一边冒烟。 理解TCP全连接队列与tcpdump抓包 1 TCP 全连接队列1.1 重谈listen函数1.2 初步理解全连接队列1.3 深入理解全连接队列 2 tcpdump抓包 1 TCP 全连接队列 1.1 重谈listen函数 这里我们使用…

【JAVA】第三张_Eclipse下载、安装、汉化

简介 Eclipse是一种流行的集成开发环境&#xff08;IDE&#xff09;&#xff0c;可用于开发各种编程语言&#xff0c;包括Java、C、Python等。它最初由IBM公司开发&#xff0c;后来被Eclipse Foundation接手并成为一个开源项目。 Eclipse提供了一个功能强大的开发平台&#x…

IDEA如何查看所有的断点(Breakpoints)并关闭

前言 我们在使用IDEA开发Java应用时&#xff0c;基本上都需要进行打断点的操作&#xff0c;这方便我们排查BUG&#xff0c;也方便我们查看设计的是否正确。 不过有时候&#xff0c;我们不希望进入断点&#xff0c;这时候除了点击断点关闭外&#xff0c;有没有更快速的方便关闭…

深度解析机器学习的四大核心功能:分类、回归、聚类与降维

深度解析机器学习的四大核心功能&#xff1a;分类、回归、聚类与降维 前言分类&#xff08;Classification&#xff09;&#xff1a;预测离散标签的艺术关键算法与代码示例逻辑回归支持向量机&#xff08;SVM&#xff09; 回归&#xff08;Regression&#xff09;&#xff1a;预…

HarmonyOS Next应用开发——图像PixelMap变换

【高心星出品】 图像变换 图片处理指对PixelMap进行相关的操作&#xff0c;如获取图片信息、裁剪、缩放、偏移、旋转、翻转、设置透明度、读写像素数据等。图片处理主要包括图像变换、位图操作&#xff0c;本文介绍图像变换。 图形裁剪 // 裁剪图片 x&#xff0c;y为裁剪的起…

impdp+remap_schema导入后登录报ORA-01017: Invalid Username/password

环境说明&#xff1a;有个11.2.0.4的rac数据库&#xff0c;现需要把USR_OA克隆一份出来做测试&#xff0c;新用户名是TEST_OA&#xff0c;直接是expdp导出用户&#xff0c;再用impdpremap_schema生成TEST_OA&#xff0c; 业务人员使用PLSQL(版本12.0.1.1814) 登录TEST_OA时总…

Python程序设计 内置函数 日志模块

logging(日志) 日志记录是程序员工具箱中非常有用的工具。它可以帮助您更好地理解程序的流程&#xff0c;并发现您在开发过程中可能没有想到的场景。 日志为开发人员提供了额外的一组眼睛&#xff0c;这些眼睛不断关注应用程序正在经历的流程。它们可以存储信息&#xff0c;例…

ShardingProxy服务端分库分表

目录 一、为什么要有服务端分库分表&#xff1f; 二、ShardingProxy基础使用 1、部署ShardingProxy 2、配置常用分库分表策略 三、ShardingSphere中的分布式事务机制 1、什么是XA事务&#xff1f; 2、实战理解XA事务 3、如何在ShardingProxy中使用另外两种事务管理器&a…

【不要离开你的舒适圈】:猛兽才希望你落单,亲人总让你回家,4个维度全面构建舒适圈矩阵

单打独斗的英雄时代已经落幕 抱团取暖才是社会寒冬的良策 自然界中&#xff0c;每个物种都占据着自己的领地和生存空间。 生态位的差异决定了它们的生存方式&#xff0c;一旦离开领地&#xff0c;失去群体的庇护&#xff0c;就会沦为野兽的美餐。 人类社会同样存在隐形圈层…

数仓建模:金字塔原理在数仓建模分析中的应用

目录 1 金字塔原理 1.1 金子塔原理基本原理 1.2 金字塔内部结构 2 如何构建金字塔 2.1 金字塔塔尖构建 2.2 金字塔纵向层次构建 2.3 金字塔横向关系构建 2.3.1 归类分组 2.3.2 逻辑递进 2.4 小结 3 金字塔原理应用 3.1 数仓建模 3.1.1 数仓建模分析方法-自上而下…

OBOO鸥柏:液晶拼接大屏搭载节点盒分布式集中管控控制系统新技术

近年来&#xff0c;随着视频监控、会议系统及展示需求的快速增长&#xff0c;KVM分布式输入输出节点控制系统在各大行业中逐渐成为核心技术。OBOO鸥柏的液晶拼接大屏分布式输入输出节点控制系统&#xff08;WControl&#xff09;&#xff0c;以其创新的技术和卓越的用户体验&am…

在线刷题系统测试报告

一、项目背景 1. 本项目是一个在线刷题系统&#xff0c;灵感来源于力扣和牛客等刷题平台&#xff0c;旨在锻炼自己的代码能力和剖析系统整体结构与各模块之间关系的能力。系统支持用户注册与登录&#xff0c;查看题目列表与题目详情&#xff0c;在线提交代码并提供反馈。 2. 该…

【命令操作】信创终端系统上timedatectl命令详解 _ 统信 _ 麒麟 _ 方德

原文链接&#xff1a;【命令操作】信创终端系统上timedatectl命令详解 | 统信 | 麒麟 | 方德 Hello&#xff0c;大家好啊&#xff01;今天给大家带来一篇关于如何在信创终端系统上使用timedatectl命令的详细介绍。timedatectl 是Linux系统中非常实用的时间管理工具&#xff0c;…

JMeter模拟并发请求

PostMan不是严格意义上的并发请求工具&#xff0c;实际是串行的&#xff0c;如果需要测试后台接口并发时程序的准确性&#xff0c;建议采用JMeter工具。 案例&#xff1a;JMeter设置20个并发卖票请求&#xff0c;查看后台是否存在超卖的情况 方式一&#xff1a;一共10张票&…

大数据-177 Elasticsearch Query DSL - 聚合分析 指标聚合 桶聚合

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; 目前已经更新到了&#xff1a; Hadoop&#xff08;已更完&#xff09;HDFS&#xff08;已更完&#xff09;MapReduce&#xff08;已更完&am…

Excel重新踩坑3:条件格式;基本公式运算符;公式中的单元格引用方式;公式菜单栏其他有用的功能说明;

0、前言&#xff1a;以下内容是学习excel公式的基础内容。 1、需求&#xff1a;将表格特定区域中数值大小大于等于30&#xff0c;小于等于80的单元格&#xff0c;颜色填充为红色&#xff0c;大于80的&#xff0c;颜色填充为黄色。 新建规则之后也可以通过该功能清除规则。 2、基…

【JavaEE初阶】网络编程TCP协议实现回显服务器以及如何处理多个客户端的响应

前言 &#x1f31f;&#x1f31f;本期讲解关于TCP/UDP协议的原理理解~~~ &#x1f308;感兴趣的小伙伴看一看小编主页&#xff1a;GGBondlctrl-CSDN博客 &#x1f525; 你的点赞就是小编不断更新的最大动力 &#x1f386;那么废话不多说…

【重学 MySQL】六十六、外键约束的使用

【重学 MySQL】六十六、外键约束的使用 外键约束的概念关键字主表和从表/父表和子表外键约束的创建条件外键约束的特点外键约束的创建方式外键约束的删除外键约束的约束等级外键约束的级联操作外键约束的示例外键约束的作用开发场景阿里开发规范 在MySQL中&#xff0c;外键约束…

免费开源的微信开发框架

近年来&#xff0c;随着人工智能技术的快速发展&#xff0c;聊天机器人在各个领域得到了广泛的应用。在社交媒体中&#xff0c;自动回复成为了一个流行的功能&#xff0c;让用户可以方便地与机器人进行互动。gewe框架&#xff0c;一个开源的微信聊天机器人框架&#xff0c;实现…

Android 10.0 Camera2 拍照镜像功能实现

1.前言 在10.0的系统rom定制化开发中,在进行camera2的相关拍照功能开发中,在某些时候会遇到拍照照片 左右镜像的问题,就是照片左半边和右半边是反的,所以就需要在拍照的时候保存图片的时候实现 左右镜像功能,接下来就来分析下拍照保存图片的流程 2.Camera2 拍照镜像功能实…