C++:拷贝构造函数和赋值运算符重载

目录

一、拷贝构造函数

1.1概念

1.2特征

二、赋值运算符重载

2.1运算符重载

2.2赋值运算符重载

2.2.1赋值运算符重载格式 

2.2.2赋值运算符重载要求

2.2.3默认生成的赋值运算符重载

2.3前置++和后置++重载


一、拷贝构造函数

1.1概念

只有一个形参,这个形参是对类类型对象的引用,在用存在的类类型对象创建时由编译器自动调用。

1.2特征

1.拷贝构造函数是创建与已经存在对象一模一样的新对象。

2.拷贝构造函数一般用const修饰。

3.拷贝构造函数是构造函数的一个重载形式。

4.拷贝构造函数的参数必须是类类型对象的引用,且参数只能有一个。

5.如果用户未定义,编译器会生成默认的拷贝构造函数。默认拷贝构造函数对内置类型对象按内存存储字节序完成浅拷贝,自定义类型是调用其自身的构造函数完成浅拷贝。

class Time
{
public:Time(){_hour = 1;_minute = 1;_second = 1;}Time(const Time& t){_hour = t._hour;_minute = t._minute;_second = t._second;cout << "Time::Time(const Time&)" << endl;}
private:int _hour;int _minute;int _second;
};
class Date
{
private:// 基本类型(内置类型)int _year = 1970;int _month = 1;int _day = 1;// 自定义类型Time _t;
};
int main()
{Date d1;// 用已经存在的d1拷贝构造d2,此处会调用Date类的拷贝构造函数// 但Date类并没有显式定义拷贝构造函数,则编译器会给Date类生成一个默认的拷贝构//造函数Date d2(d1);return 0;
}

6. 虽然编译器会生成默认的拷贝构造函数,但仅仅会完成浅拷贝,如果拷贝的函数涉及空间申请(如stack),则会出现错误(两个函数会申请到同一块空间,销毁时会出现同一块空间释放2次,导致程序崩溃)。

typedef int DataType;
class Stack
{
public:Stack(size_t capacity = 10){_array = (DataType*)malloc(capacity * sizeof(DataType));if (nullptr == _array){perror("malloc申请空间失败");return;}_size = 0;_capacity = capacity;}void Push(const DataType& data){// CheckCapacity();_array[_size] = data;_size++;}~Stack(){if (_array){free(_array);_array = nullptr;_capacity = 0;_size = 0;}}
private:DataType* _array;size_t _size;size_t _capacity;
};
int main()
{Stack s1;s1.Push(1);s1.Push(2);s1.Push(3);s1.Push(4);Stack s2(s1);return 0;
} 

 上述代码中s2和s1申请了同一块空间,释放时导致程序崩溃。  

二、赋值运算符重载

2.1运算符重载

1.C++为了增强代码的可读性,增加了运算符重载的概念,支持自定义函数的操作符运算。

2.运算符重载是一个有着特殊函数名的函数,有返回值,有参数、函数名等。

3.函数名为:operator加上要重载的操作符

4.标准模板:

返回值类型 operator操作符(参数)

: 

1.operator后的操作符不能自己创建,必须是已含的操作符。

	bool operator@(const Date & d2)//非已含的操作符{//报错return _year == d2._year&& _month == d2._month&& _day == d2._day;}

2.重载操作符必须有一个类类型的参数。

	bool operator==()//参数过少{return _year == d2._year&& _month == d2._month&& _day == d2._day;}

3.用于内置类型的运算符,不会随运算符重载改变其本身含义。

// 定义一个复数类
class Complex 
{
public:// 成员变量:实部和虚部double real;double imag;// 构造函数Complex(double r = 0.0, double i = 0.0) : real(r), imag(i) {}// 重载加法运算符,使得两个Complex对象可以相加Complex operator+(const Complex& other) const {return Complex(real - other.real, imag - other.imag);//将减法重载成加法}// 为了方便打印,重载<<运算符friend ostream& operator<<(std::ostream& os, const Complex& c) {os << c.real << " + " << c.imag << "i";return os;}
};int main() 
{Complex num1(3, 4);  // 创建复数3 + 4iComplex num2(1, -1); // 创建复数1 - 1iComplex sum = num1 + num2; // 使用重载的+运算符int a = 2;int b = 3 + a;cout << "Sum: " << sum << endl; // 输出相加结果cout << "b: " << b << endl;return 0;
}

 

上图中,我故意将减法重载成加法,Sum执行的+是我重载的减法,但b执行的还是加法,说明内置类型的运算符不受重载运算符的影响。 

4.类的成员函数重载时,形参比操作数少1,因为成员函数的第一个参数是隐藏的this(C++:类的对象模型和this指针中有介绍)。

bool operator==( Date & d2)//只有一个参数但有两个操作数
{return _year == d2._year&& _month == d2._month&& _day == d2._day;
}

上面图片的代码在编译器眼中是下图这样 

	bool operator==( Date & d2){return this->_year == d2._year&& this->_month == d2._month&& this->_day == d2._day;}

5.   (.*)  (::)   (sizeof)  (?:)  (.)  前面括号内的5个操作符不能重载。   

2.2赋值运算符重载

2.2.1赋值运算符重载格式 

1.参数类型:const T&,传递引用可以提高传参效率。

2.返回值:*this,返回引用可以提高返回的效率,有返回值是为了支持连续的赋值

3.要检验是否会自己给自己赋值

Date& operator=(const Date& d)//参数类型含有const,防止改变参数
{if (this != &d)//检验是否会自己给自己赋值{_year = d._year;_month = d._month;_day = d._day;}return *this;//返回*this方便连续赋值
}

2.2.2赋值运算符重载要求

 赋值运算符只能重载成类的成员函数不能重载成全局函数。用户如果不写赋值运算符重载,编译器会自动生成一个默认的赋值运算符重载,与全局的运算符重载冲突。

class Date
{
public:Date(int year = 1900, int month = 1, int day = 1){_year = year;_month = month;_day = day;}int _year;int _month;int _day;
};
Date& operator=(Date& left, const Date& right)//全局函数
{if (&left != &right){left._year = right._year;left._month = right._month;left._day = right._day;}return left;
}

2.2.3默认生成的赋值运算符重载

 编译器默认生成的赋值运算符重载以值的方式逐字节拷贝。对于内置类型成员变量是直接赋值的(浅拷贝),对于自定义类型成员变量需要调用对应类的赋值运算符完成赋值。

: 编译器自动生成的赋值运算符重载是浅拷贝,对于无空间申请的函数可以(如Date),对于有空间申请的函数就不可以(如Stack),必须自己写。

class Time
{
public:Time(){_hour = 1;_minute = 1;_second = 1;}Time& operator=(const Time& t){if (this != &t){_hour = t._hour;_minute = t._minute;_second = t._second;}return *this;}
private:int _hour;int _minute;int _second;
};
class Date
{
private:// 基本类型(内置类型)int _year = 1970;int _month = 1;int _day = 1;// 自定义类型Time _t;
};
int main()
{Date d1;Date d2;d1 = d2;return 0;
}

2.3前置++和后置++重载

前置++:返回+1之后的结果
后置++:返回+1之前的结果

前置++和后置++都是一元运算符,为了让前置++与后置++形成能正确重载。
 C++规定:后置++重载时多增加一个int类型的参数,但调用函数时该参数不用传递,编译器
自动传递。
 注意:后置++是先使用后+1,因此需要返回+1之前的旧值,故需在实现时需要先将this保存
一份,然后给this + 1(存在额外空间的使用)。

故更推荐使用前置++。

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

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

相关文章

leetcode51.N皇后(困难)-回溯法

思路 都知道n皇后问题是回溯算法解决的经典问题&#xff0c;但是用回溯解决多了组合、切割、子集、排列问题之后&#xff0c;遇到这种二维矩阵还会有点不知所措。 首先来看一下皇后们的约束条件&#xff1a; 不能同行不能同列不能同斜线 确定完约束条件&#xff0c;来看看究…

Python爬虫(入门版)

1、爬虫是什么 简单的来说&#xff1a;就是用程序获取网络上数据。 2、爬虫的原理 如果要获取网络上数据&#xff0c;我们要给爬虫一个网址&#xff08;程序中通常叫URL&#xff09;&#xff0c;爬虫发送一个HTTP请求给目标网页的服务器&#xff0c;服务器返回数据给客户端&am…

异地组网、网络部署、无线覆盖,贝锐蒲公英一步到位

面对网络架构复杂的企业总部&#xff0c;分散在各地的分支机构&#xff0c;以及出差的远程办公人员&#xff0c;如何才能高效异地组网&#xff1f; 为了确保总部、分部网络实现远程稳定、高速互访&#xff0c;以及远程人员安全访问总部业务系统&#xff0c;基于自研SD-WAN的贝…

C++ 小游戏:战斗之旅

一、游戏名称&#xff1a;战斗之旅 游戏规则 角色选择&#xff1a;玩家可以选择不同的角色&#xff0c;每个角色都有不同的属性和技能。商城&#xff1a;玩家可以访问商城购买不同的装备&#xff0c;包括武器和回复物品。战斗&#xff1a;玩家可以与其他角色进行战斗。在战斗…

数据结构(01)——链表OJ

目录 移除链表元素 思路1 不创建虚拟头节点 思路2 创建虚拟头节点 反转链表 寻找链表中间节点 判断链表是否相交 回文链表 环形链表 环形链表|| 移除链表元素 . - 力扣&#xff08;LeetCode&#xff09; 要想移除链表的元素&#xff0c;那么只需要将目标节点的前一…

XMind轮播图banner测试点

banner测试点 显示1到5张banner图片 [1,5] 6 1 一张不轮播 5 3 0可选 自动轮播,3秒切换一张 鼠标悬停,不轮播 实心为当前图 点击可以跳转 点击左,切换一张图片 点击右, 切换一张图片…

【中级软件设计师】上午题12-软件工程(3):项目活动图、软件风险、软件评审、软件项目估算

【中级软件设计师】上午题12-软件工程&#xff08;3&#xff09; 1 软件项目估算1.1 COCOMO估算模型1.2 COCOMOⅡ模型 2 进度管理2.1 gantt甘特图2.2 pert图2.3 项目活动图2.3.1 画项目图 3 软件配置管理4 软件风险4.1 风险管理4.2 风险识别4.3 风险预测4.4 风险评估4.5 风险控…

Baidu comate智能编程助手评测

Baidu comate智能编程助手评测 作者&#xff1a;知孤云出岫 目录 一&#xff0e; 关于comate产品 二&#xff0e; 关于comate产品体验 三&#xff0e; 关于实际案例. 四&#xff0e; 关于baidu comate编程助手的实测体验感悟 五&#xff0e; …

Java包装类,128陷阱

包装类 基本数据类型都有自己对应的包装类&#xff0c;因为Java本质是面向对象编程的&#xff0c;一切的内容在Java看来都是对象 但是基本数据类型没有类&#xff0c;也没有对象&#xff0c;这样就有了矛盾 所以诞生了基本类型的包装类 基本数据类型&#xff1a; byte,short,…

014、Python+fastapi,第一个后台管理项目走向第14步:建立python+fastapi项目,创建common通用模块

一、说明 通用模块主要是完成文件的上传下载&#xff0c;抄吧&#xff0c;要不然怎么叫通用模块呢&#xff1f; 我把RuoYi-Vue3-FastAPI中的验证码模块放在这里了&#xff0c;我觉得验证也比较通用吧&#xff0c; 二、添加common通用模块 1、通用模块没有数据表&#xff0c…

冯喜运:4.30现货黄金涨跌互现,最新黄金原油趋势分析

【黄金消息面分析】&#xff1a;上周五公布的数据&#xff0c;美国3月核心PCE年率维持前值不变&#xff0c;美国4月一年期通胀率预期上升&#xff0c;显示通胀顽固并有所回升&#xff0c;但其经济数据美国3月个人支出月率和美国4月密歇根大学消费者信心指数终值则低于预期和前值…

WEB攻防-PHP特性-metinfoCMS审计实例

前置知识&#xff1a;PHP函数缺陷 测试环境&#xff1a;MetInfo CMS 函数缺陷导致的任意文件读取 漏洞URL&#xff1a;/include/thumb.php?dir 漏洞文件位置&#xff1a;MetInfo6.0.0\app\system\include\module\old_thumb.class.php <?phpdefined(IN_MET) or exit(No…

深度学习 --- stanford cs231学习笔记(一)

stanford cs231学习笔记(一) 1&#xff0c;先是讲到了机器学习中的kNN算法&#xff0c;然后因为kNN分类器的一些弊端&#xff0c;引入了线性分类器。 kNN算法的三大弊端&#xff1a; (1)&#xff0c;计算量大&#xff0c;当特征比较多时表示性差 (2)&#xff0c;训练时耗时少…

HF区块链链码基础

链码生命周期 一 . 链码准备 准备文件 . 在测试目录下创建chaincode,拷贝测试链码进 chaincode目录,拷贝 set-env.sh 脚本进 scripts 目录 二. 打包链码 打包测试链码 export FABRIC_CFG_PATH${PWD}/config peer lifecycle chaincode package ./chaincode/chaincode_basic.…

每周一算法:单源次短路

题目描述 “您的个人假期”旅行社组织了一次比荷卢经济联盟的巴士之旅。 比荷卢经济联盟有很多公交线路。每天公共汽车都会从一座城市开往另一座城市。沿途汽车可能会在一些城市&#xff08;零或更多&#xff09;停靠。 旅行社计划旅途从 S S S 城市出发&#xff0c;到 F …

C语言进阶|链表经典OJ题

✈移除链表元素 给你一个链表的头节点 head 和一个整数 val &#xff0c;请你删除链表中所有满足 Node.val val 的节点&#xff0c;并返回 新的头节点 。 方法一&#xff1a; 遍历链表找到所有等于val的节点&#xff0c;再执行删除操作删除这些节点。 方法二&#xff1a; …

算法必备数学基础:图论方法由浅入深实践与应用

作者介绍&#xff1a;10年大厂数据\经营分析经验&#xff0c;现任大厂数据部门负责人。 会一些的技术&#xff1a;数据分析、算法、SQL、大数据相关、python 欢迎加入社区&#xff1a;码上找工作 作者专栏每日更新&#xff1a; LeetCode解锁1000题: 打怪升级之旅 python数据分析…

SparkSQL---简介及RDD V.S DataFrame V.S Dataset编程模型详解

一、SparkSQL简介 SparkSQL&#xff0c;就是Spark生态体系中的构建在SparkCore基础之上的一个基于SQL的计算模块。SparkSQL的前身不叫SparkSQL&#xff0c;而叫Shark&#xff0c;最开始的时候底层代码优化&#xff0c;sql的解析、执行引擎等等完全基于Hive&#xff0c;总之Sha…

2024年水资源保护盛事,“澜湄周”邀请国信华源加入!

4月26日&#xff0c;2024年水资源领域“澜湄周”活动在北京举行。水利部国科司、外交部亚洲司和边海司、湄公河五国驻华使馆以及澜湄水资源合作单位的代表嘉宾出席活动。北京国信华源公司特邀参加&#xff0c;现场就深化澜湄水资源合作展开深入交流研讨。 澜湄六国&#xff0c;…

2022-2003年上市公司企业商业信用融资数据

01、数据简介 企业商业信用融资是指企业之间在买卖商品时&#xff0c;以商品形式提供的借贷活动。这种融资方式是经济活动中一种最普遍的债权债务关系。商业信用的存在对于扩大生产和促进流通起到了十分积极的作用&#xff0c;但不可避免的也存在着一些消极的影响。 测算方式…