C++拷贝构造函数、赋值学习整理:

拷贝构造函数:

概念:

构造函数的第一个参数,是类本身的const引用(一般情况下没有其他参数,少数情况:其他参数必须有默认值!)称此类构造函数为拷贝构造函数

特征:

1:拷贝构造函数类名与函数值一致,没有返回值(与构造函数一致)

2:每个类都有拷贝构造函数,未定义时系统自动生成(可能产生错误)

      默认生成的拷贝构造函数:为每个成员分配内存空间、成员变量赋值(浅拷贝)

3:调用时只有一个实参,要求函数不能重载

      调用时仅对象作为实参,后面若有参数都为默认值,无法区分函数导致无法重载

4:第一个参数是类本身的const引用,存在其他有默认值的参数

//格式:
类名(const 类名&对象名);
class CPY
{
    public:
    CPY();//默认构造函数;
    CPY(const CPY& a);//拷贝构造函数
    ...
};

拷贝构造函数的应用:

  • 用已经存在的对象初始化构造新的对象
  • 以类本身对象作为函数传递的实参,在非引用情况下(程序需要在函数中新创建一个相同的对象并复制值
  • 返回类型为非引用类型的函数返回一个对象
int main()
{
    CPY a{...};//构造
    CPY b(a);//拷贝构造
    CPY c=a;//拷贝构造
    MAX(a);//-> int MAX(const CPY a) //函数五引用对象传参:拷贝构造用于传参

    MAX(a,b)//->CPY MAX(const CPY& a,const CPY& b) return a;
        //有引用的传参不是拷贝构造函数
        //函数返回值使用拷贝构造函数
    }

注意:

拷贝构造函数是一种特殊的构造函数,其形参是本类对象的引用,且这个参数几乎总是const的引用。

拷贝构造函数作用即将一个已经存在的对象用于初始化构造新的对象,我们没有定义拷贝构造函数时,系统将自动构造拷贝构造函数:从给定对象中依次将每个非static成员拷贝到正在创建的新对象中。即分以下几种情况:

    1. 当该类的对象都是普通变量,默认拷贝构造函数可完成值的拷贝(浅拷贝),正确
    2. 当类的对象中出现指针、数组等变量,默认函数拷贝原来对象成员中的值到新创建的指针的值、数组的首地址(浅拷贝),错误
      1. 原因以下浅拷贝仅仅拷贝值,导致多处指针指向同一地址,当其中多对象生命周期结束时析构函数将指针同一地址多次释放导致系统崩溃
      2. 解决方法自定义拷贝构造函数使用深拷贝创建一新指针、数组(指向不同地址),再将其对象成员的指针、数组值赋值给新创建的对象成员(strcpy()或memcpy()),即得到指向不同地址的同值对象成员,满足拷贝构造函数、析构函数要求;
  1. 拷贝构造函数的参数采用引用方式,若是非引用:为调用拷贝构造函数需复制实参到形参,由复制的需要又得重新调用拷贝构造函数,产生无限循环;而引用即调用对象本身,无需复制

引例:

class Complex //复数类
{
    public:
    Complex(double r, double i);
    Complex(const Complex& c);
    Complex add(Complex c);//加法
    private:
    double real;    //实部
    double image;   //虚部
};
Complex::Complex(double r, double i) :real(r), image(i)
{
    cout << "构造函数,实部:"<<real<<",虚部:"<<image << endl;
}
Complex::Complex(const Complex & c)
{
    real = c.real;
    image = c.image;
    cout << "拷贝构造函数,实部:" << real << ",虚部:" << image << endl;
}

Complex Complex::add(Complex c) 
{
    Complex y(real + c.real, image + c.image); //构造函数
    return y;//返回值为类对象,会调用拷贝构造函数
}
void f(Complex n) //参数是类对象,会调用拷贝构造函数
{
    cout << "f(Complex n)" << endl;
}
int main()
{
    Complex a(3, 4); //调用构造函数
    Complex b(6.5, 7.5);//调用构造函数
    Complex c(a); //拷贝构造函数
    Complex d = c;//拷贝构造函数,注意和下一节的赋值区分开

    f(b); //拷贝构造函数
    c = a.add(b); //拷贝构造函数

    return 0;
}

程序分析:

  • 调用构造函数,创建了两个复数类对象a和b

  • 用已知对象初始化另一个对象,系统调用拷贝构造函数

  • 利用c初始化对象d,这一句看似=赋值,其实还是调用拷贝构造函数,因为这里还是初始化过程。
  • Complex d=c 等同 Complex d(c) 等同 Complex d{c},

  • 将实参b传给形参n,因为形参是非引用的类对象,调用拷贝构造函数。

  • 首先实参b传递给非引用形参c会调用拷贝构造函数,接着在add函数中定义了一个复数类对象y(24行),系统会调用构造函数。
  • 最后,函数add的返回值是一个非引用对象,系统会创建一个临时对象,将局部对象y赋值给临时对象,这时也要调用拷贝构造函数。

赋值:

同类的对象之间可以互相赋值,即一个对象的值可以赋值给另一个对象。对象之间的赋值通过“=”进行。默认就是把一个对象所有非static数据成员的值依次赋值给另一个对象。

//格式
对象名1 = 对象名2;

说明:

(1)对象的赋值只对其中的数据成员赋值,不对成员函数赋值。

每个对象的数据成员占用独立的存储空间,不同对象的数据成员占有不同的存储空间,赋值的过程是将一个对象的数据成员在存储空间的值复制给另一个对象的数据成员的存储空间。

而不同对象的成员函数是同一个函数代码段不需要、也无法对它们赋值

(2)类的数据成员中不能包括动态分配的数据,否则在赋值时可能出现意想不到的严重后果,(不同指针指向同一地址后多次释放delete,崩溃)

如果类的数据成员有指针,则一定要实现如下函数

1、构造函数 (如果没有,会出现野指针)

2、拷贝构造函数(如果没有,会出现浅拷贝)

3、重载 = 符号 (如果没有,会出现浅拷贝)

2、析构函数(内存泄漏)

        delete动态对象则自动调用析构函数,不delete不调用析构函数

        而动态成员需系统调用析构函数delete

拷贝构造函数与赋值区分:拷贝构造定义初始化阶段,赋值在定义完成后进行。

运算符重载

在类中重新定义运算符,赋予运算符新的功能适应类的运算,如果某个运算符重载了,那么在使用该运算符时,系统会自动调用。

格式如下:

返回值类型 operator 运算符(参数);
//注意 operator关键字必须写

//例如:
    operator +()//表示:重载+运算符
    operator *()//表示:重载*运算符。

其中,operator 是 C++的关键字,专门用于定义运算符重载函数

运算符重载是一种形式的C++多态,它使得对象操作更直观,本质上也是属于函数重载

 假设有一个Student类,并为它定义了一个operator +()成员函数,以重载+运算符,如果有Student的对象s1,s2,s3。便可以编写这样的代码。

s1 = s2+s3; //简化
s1 = s2.operator+(s3);//复杂写法

已使用的引例:

1. 这是因为C++已经对string类重载了“+”运算符加法:

        string s1="abc";string ;s2="xyz"; s1+s2;

2. C++对“<<”和“>>”进行了重载,用户在不同的场景下使用它们,作用是不同的。

对于位运算而言:“<<”运算符是左移运算符,“>>”运算符是右移运算符

        “<<”运算符在输出操作中与流对象cout配合使用,是流插入运算符

        “>>”运算符在输入操作中与流对象cin配合使用,是流提取运算符

注意:运算符重载的赋值函数,要添加以下代码:避免同对象赋值判断

if(this==&s)
return;
// s 是实参地址
//防止同一地址相互赋值,先delete释放地址导致数据丢失

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

使用Animate.css动画库

1.网站&#xff1a;Animate.css | A cross-browser library of CSS animations. 样式&#xff1a;Animate.css 一款强大的预设css3动画库 (jq22.com) 一、引入 命令提示符/终端&#xff1a; npm install animate.css --save 二、 全局导入&#xff08;在main.js&#xff0…

Obsidian笔记软件结合cpolar实现安卓移动端远程本地群晖WebDAV数据同步

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

如何编写高质量测试用例?

&#x1f345; 视频学习&#xff1a;文末有免费的配套视频可观看 &#x1f345; 点击文末小卡片 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;薪资嘎嘎涨 测试场景&#xff1a; 为登录功能设计测试用例 测试员为什么要会编测试用例 测试员的目标是…

HAL STM32+EC11编码器实现增减调节及单击、双击、长按功能

HAL STM32EC11编码器实现增减调节及单击、双击、长按功能 &#x1f4fa;实现效果演示&#xff1a; &#x1f4d8;内容提要 &#x1f4dd;本文主要实现&#xff0c;通过STM32 HAL库开发&#xff0c;实现的EC11编码器功能&#xff0c;按键结合状态机思想实现的拓展单击、双击、…

win下安装es可视化工具——elasticsearch head(win_Elasticsearch)

一、head简介 Elasticsearch Head是集群管理、数据可视化、增删改查、查询语句可视化工具。 二、node.js的安装 ElasticSearch-head 依赖于node.js 下面先安装node.js 下面是node.js下载地址http://nodejs.cn/download/&#xff1b; 下载后&#xff0c;就是一个安装包&#xf…

如何在Ubuntu安装配置SVN服务端并实现无公网ip访问内网资料库

&#x1f308;个人主页: Aileen_0v0 &#x1f525;热门专栏: 华为鸿蒙系统学习|计算机网络|数据结构与算法 ​&#x1f4ab;个人格言:“没有罗马,那就自己创造罗马~” 文章目录 前言1. Ubuntu安装SVN服务2. 修改配置文件2.1 修改svnserve.conf文件2.2 修改passwd文件2.3 修改au…

Java可以用于物联网的开发吗?

Java可以用于物联网的开发吗? 在开始前我有一些资料&#xff0c;是我根据网友给的问题精心整理了一份「Java的资料从专业入门到高级教程」&#xff0c; 点个关注在评论区回复“888”之后私信回复“888”&#xff0c;全部无偿共享给大家&#xff01;&#xff01;&#xff01;J…

备忘录记事本内容转移到新手机的方法

在日常的工作和生活中&#xff0c;我习惯用备忘录来记录一切&#xff1a;工作的要点、买菜的清单、生活的琐事……这些看似微小的记录&#xff0c;却是我生活的重要组成部分。然而&#xff0c;每次换手机&#xff0c;我总是面临一个难题&#xff1a;如何将旧手机上的备忘录内容…

下沉市场哪些品牌正当红?“下沉同花顺”异军突起

文 | 螳螂观察 作者 | 易不二 2023年的消费市场&#xff0c;越来越多“农村包围城市”的下沉品牌&#xff0c;以亮眼的表现成为拉动消费复苏的主力军。 全球36000多家门店的蜜雪冰城&#xff0c;向港交所递表冲刺IPO&#xff1b;两大量贩零食巨头赵一鸣零食与零食很忙战略合…

一个响指,代码生成!华为云CodeArts Snap正式公测

月初&#xff0c;华为云CodeArts Snap正式开启公测&#xff0c;这是一款基于华为云研发大模型的智能化编程助手&#xff0c;旨在为开发者提供高效且智能的编程体验&#xff0c;提升研发人员的单兵作战能力。 如今&#xff0c;生成式AI爆发式增长&#xff0c;大模型商用节奏加快…

JVM/GC复习

JVM/GC JVM(java虚拟机)MATjstack(将正在运行的JVM的线程进行快照并且打印出来)死锁VisualVM工具(监控线程内存使用情况)JMX GC垃圾回收算法1.引用计数法2.标记清除发3.标记压缩算法4.复制算法5.分代算法 收集器1.串行垃圾收集器2.并行垃圾收集器2.CMS垃圾收集器 3.G1垃圾收集器…

威联通QNAP NAS结合cpolar内网穿透实现公网远程访问NAS中存储的文件

文章目录 推荐 前言1. 威联通安装cpolar内网穿透2. 内网穿透2.1 创建隧道2.2 测试公网远程访问 3. 配置固定二级子域名3.1 保留二级子域名3.2 配置二级子域名 4. 使用固定二级子域名远程访问 推荐 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣…

一文了解prettier

简介 eslint和prettier都是用来做代码格式化的&#xff0c;他们其中又分为npm包和vscode插件&#xff0c;顺序是&#xff1a;先有npm包再有vscode插件 eslint限制工具 作用&#xff1a; 检查代码规范变量声明是否调用是否有console.log()语句… 用法 新建index.js文件 //…

MySQL数据库的锁机制

目录 一、引言 二、锁的类型及作用 2.1 行级锁 2.2 间隙锁与临键锁 2.3 共享锁与排他锁 2.4 意向锁 2.5 表级锁 2.6 元数据锁 三、锁的管理与优化 3.1 合理设置事务隔离级别 3.2 避免长事务 3.3 索引优化 3.4 明确锁定范围 3.5 避免不必要的全表扫描 四、实战分…

JDBC数据库连接

JDBC(Java DataBase Connectivity)就是用Java语言操作关系型数据库的一套API JDBC的步骤固定&#xff0c;大体分为8个步骤&#xff0c;以MySQL数据库为例 1.创建工程并导入驱动jar包 2.注册驱动 注册驱动的目的是告诉代码要执行哪一个jar包 Class.forName(com.mysql.jdbc.D…

多尺度特征融合13种创新方案全面汇总,含2024年最新

前段时间和大佬朋友交流学术的时候&#xff0c;发现目前发论文最好用的2大创新方式一是加注意力机制&#xff0c;二是多尺度特征融合。上回我们讲过了加注意力机制&#xff0c;今天我们就来聊聊多尺度特征融合。 多尺度特征融合是一种在图像处理和CV中使用的技术&#xff0c;由…

05-Seata下SQL使用限制

不支持 SQL 嵌套不支持多表复杂 SQL(自1.6.0版本&#xff0c;MySQL支持UPDATE JOIN语句&#xff0c;详情请看不支持存储过程、触发器部分数据库不支持批量更新&#xff0c;在使用 MySQL、Mariadb、PostgreSQL9.6作为数据库时支持批量&#xff0c;批量更新方式如下以 Java 为例 …

大创项目推荐 题目:垃圾邮件(短信)分类 算法实现 机器学习 深度学习 开题

文章目录 1 前言2 垃圾短信/邮件 分类算法 原理2.1 常用的分类器 - 贝叶斯分类器 3 数据集介绍4 数据预处理5 特征提取6 训练分类器7 综合测试结果8 其他模型方法9 最后 1 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 基于机器学习的垃圾邮件分类 该项目…

网络协议与攻击模拟_09部署DHCP服务器

一、部署DHCP服务器 Windows server部署DHCP服务器 1、虚拟机网络架构理解 Vmware里面不同的虚拟机可以设置相同的Vmnet网络&#xff0c;也可以设置不同的Vmnet网络。两台虚拟机设置相同的Vmnet1网卡&#xff0c;可以看作为使用虚拟交换机将两台Vmnet1的虚拟机连接起来的。 …

在使用springboot框架式的的script无法通过${}来获取值

今天使用springboot框架做项目&#xff0c;想着来实现一下搜索的下拉框回显功能&#xff0c;然后就一直在报错误&#xff0c;关键是报的错误牛头不对马嘴&#xff0c;检查了一下后端代码&#xff0c;发现没什么问题&#xff0c;就把目光聚焦了.jsp页面的代码 <script type&…