C++运算符重载中的引用返回

文章目录

  • 引言
  • 原因
    • 1.为了支持链式调用
    • 2.避免不必要的对象创建和复制
    • 3.保持语义一致性

引言

在C++编程语言中,运算符重载是一项强大的特性,它允许程序员为自定义类型重新定义或重载已有的运算符,从而使得这些类型能够像内置类型一样使用运算符。这不仅提高了代码的可读性和易用性,还使得复杂的操作可以通过简洁的语法来表达。而在运算符重载的过程中,返回值的类型选择是一个重要的设计决策,其中引用返回尤为关键。

引用返回在C++运算符重载中扮演着至关重要的角色。通过返回引用,我们可以实现链式操作、修改原始对象状态以及避免不必要的对象复制等。这些特性使得引用返回在构建高效、灵活的C++代码时成为不可或缺的工具。

然而,引用返回也带来了一些潜在的问题和挑战。例如,如果不正确地使用引用返回,可能会导致程序出现难以察觉的错误或不可预测的行为。因此,在使用引用返回时,我们需要仔细考虑其适用的场景和潜在的风险,并遵循一些最佳实践来确保代码的正确性和可靠性。


原因

以下是一个具体的例子,展示了为什么重载有些运算符时要返回自身的引用:

class MyClass {
public:int value;MyClass(int v = 0) :value(v) {std::cout << " MyClass(int v) " << std::endl;}MyClass(const MyClass& v) :value(v.value) {std::cout << " MyClass(const MyClass& v) " << std::endl;}~MyClass() {std::cout << " ~MyClass() " << std::endl;}// 重载赋值运算符,返回自身的引用  MyClass& operator=(const MyClass& other) {if (this != &other) { // 防止自赋值  value = other.value;}return *this; // 返回自身的引用  }MyClass& operator+=(const MyClass& other) {value += other.value;return *this; // 返回自身的引用  }
};int main() {MyClass a(10);MyClass b(20);MyClass c(30);// 使用链式赋值   a += b += c;std::cout << a.value << std::endl; 	//60std::cout << b.value << std::endl;	//50std::cout << c.value << std::endl	//30a = b =c; // 输出a的值,应为30,因为a = b = c;相当于a = (b = c);  std::cout << a.value << std::endl;	//30std::cout << b.value << std::endl;	//30std::cout << c.value << std::endl;	//30return 0;
}

1.为了支持链式调用

在这个例子中,MyClass 类重载了赋值运算符,使其返回自身的引用。在 main 函数中,a = b = c; 语句使用了链式赋值。首先,c 的值赋给 b,然后 b 的值(现在已经被赋值为 c 的值)再赋给 a。由于赋值运算符返回了 MyClass类型,这使得链式赋值成为可能。

但是如若我们返回值改为void

void MyClass::operator+=(const MyClass& other) {value += other.value;
}// 使用链式赋值   
a = b;
b = c;
a += b += c;
//error C2679: 二元“+=”: 没有找到接受“void”类型的右操作数的运算符(或没有可接受的转换)

返回引用使得链式调用成为可能。例如,在a += b += c;这样的语句中,b += c首先执行,并返回b对象的引用。然后,这个返回的引用被用于a +=操作。如果operator+=不返回本类型变量,而是返回void,那么a +=将不会正确地工作。

2.避免不必要的对象创建和复制

如果operator+=operator=返回一个对象而不是引用,我们修改代码:

MyClass MyClass::operator+=(const MyClass& other) {value += other.value;return *this; // 返回自身的引用  
}int main(){MyClass a(10);MyClass b(20);MyClass c(30);a += b += c;
}

运行结果:
在这里插入图片描述

那么每次调用该运算符时都会创建一个新的临时对象来存储结果。这不仅增加了内存分配和释放的开销,还可能导致不必要的对象复制,降低了代码的效率。通过返回引用,我们可以直接修改并返回原始对象,避免了这些额外的开销。

3.保持语义一致性

在C++中,内置的运算符(如+=)通常返回其左侧操作数的引用。对于自定义类型,重载这些运算符以返回引用可以保持与内置类型相似的行为,这有助于保持代码的语义一致性和可读性。

是的,在C++中,对于自定义类型,重载运算符时返回引用是一个常见的做法,特别是针对类似+=、-=等复合赋值运算符。通过返回左侧操作数的引用,可以实现链式调用和保持与内置类型相似的行为,增强代码的可读性和一致性。

例如,如果我们有一个自定义的Vector类,并希望支持向量的加法操作,可以这样重载+=运算符:

class Vector {
private:int x, y;public:Vector(int x, int y) : x(x), y(y) {}// 重载 += 运算符Vector& operator+=(const Vector& other) {x += other.x;y += other.y;return *this; // 返回左侧操作数的引用}
};

通过返回*this(即左侧操作数)的引用,我们可以像内置类型一样使用+=运算符,并支持链式调用:

Vector v1(1, 2);
Vector v2(3, 4);
v1 += v2 += Vector(5, 6);

这样做不仅使代码更易读和直观,还能保持与内置类型的行为一致性,提高代码的可维护性和可读性。

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

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

相关文章

离线linux服务器安装mysql8

本文的服务器环境&#xff1a;openEuler毛坯版的&#xff0c;很多常用的指令都没有预装&#xff0c;比如rpm、tar等等&#xff0c;没有网络坏境&#xff0c;需要自己手动配置本地yum仓库&#xff0c;安装相关指令 1、检查服务器是否已经安装了MySQL 1.1、查询mysql以安装的相关…

使用Docker本地搭建蚂蚁笔记并实现无公网IP远程访问

文章目录 1. 安装Docker2. Docker本地部署Leanote蚂蚁笔记3. 安装cpolar内网穿透4. 固定Leanote蚂蚁笔记公网地址 本篇文章介绍如何使用Docker部署Leanote蚂蚁笔记&#xff0c;并且结合cpolar内网穿透实现公网远程访问本地笔记编辑并制作个人博客等。 Leanote 蚂蚁笔记是一款云…

Echarts 仪表盘

1、效果图 2、代码 createTenantChartOne(){var myChart1 this.$echarts.init(document.getElementById(tenant-chart-1));var dataArr 82;var title 仪表盘;let option {graphic: {type: text,left: center,top: 85%,style: {text: title,textAlign: center,//居中对齐fi…

微服务高级篇(五):可靠消息服务

文章目录 一、消息队列MQ存在的问题&#xff1f;二、如何保证 消息可靠性 &#xff1f;2.1 生产者消息确认【对生产者配置】2.2 消息持久化2.3 消费者消息确认【对消费者配置】2.4 消费失败重试机制2.5 消费者失败消息处理策略2.6 总结 三、处理延迟消息&#xff1f;死信交换机…

application.properties 里面和 application.yml 里面都配置了同样的参数 ,哪个会生效

在Spring Boot中&#xff0c;如果application.properties和application.yml&#xff0c;application-dev.yml&#xff08;application.yml中指定了avtive: dev&#xff09;中同时配置了相同的参数&#xff0c;Spring Boot默认会按照一定的加载顺序加载配置文件&#xff0c;并且…

【保姆级带你了解机器学习的概念,步骤,分类和实践】

&#x1f525;博主&#xff1a;程序员不想YY啊&#x1f525; &#x1f3c6;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家&#x1f3c6; &#x1f917;点赞&#x1f388;收藏⭐再看&#x1f4ab;养成习惯 &#x1f91d;希望本文对您有所裨益&#xff0c;如有…

方案功能开发:智能机器人玩具

玩具电动趣萌机器人方案开发定制&#xff0c;东莞市酷得智能科技有限公司是研发型芯片贸易公司&#xff0c;可为制造厂商朋友定制软件底层方案。下面介绍一下机器人方案可实现的功能&#xff1a; 基础功能&#xff1a; 方向&#xff1a;前进&#xff0c;后退&#xff0c;左转&a…

springboot项目中如何实现邮件告警功能(监控平台服务模拟)

介绍 模拟服务器故障&#xff0c;然后实现邮件告警 一、首先配置邮件的maven依赖 代码如下&#xff1a; <!--邮件告警--><!-- Spring Boot的邮件发送依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spri…

【嵌入式——QT】多语言界面

【嵌入式——QT】多语言界面 多语言页面开发步骤tr()函数 多语言页面开发步骤 第一步 在你编写的代码中添加tr()函数&#xff0c;方便之后可以精准的定位到你所需要翻译的部分。 第二步 在.pro文件中添加以下代码&#xff0c;这样会让你生成相应的.ts文件&#xff0c;ts文件是…

深度学习Top10算法之深度神经网络DNN

深度神经网络&#xff08;Deep Neural Networks&#xff0c;DNN&#xff09;是人工神经网络&#xff08;Artificial Neural Networks&#xff0c;ANN&#xff09;的一种扩展。它们通过模仿人脑的工作原理来处理数据和创建模式&#xff0c;广泛应用于图像识别、语音识别、自然语…

安捷伦Agilent 85033E机械校准套件

181/2461/8938产品概述&#xff1a; 网络分析中的测量误差可分为两类:随机误差和系统误差。随机误差和系统误差都是矢量。随机误差是不可重复的测量变化&#xff0c;通常是不可预测的。系统误差是测试设置中可重复的测量变化。 系统误差包括阻抗不匹配、系统频率响应和测试设…

javaSwing超级玛丽游戏

一、摘要 摘要 近年来&#xff0c;Java作为一种新的编程语言&#xff0c;以其简单性、可移植性和平台无关性等优点&#xff0c;得到了广泛地应用。J2SE称为Java标准版或Java标准平台。J2SE提供了标准的SDK开发平台。利用该平台可以开发Java桌面应用程序和低端的服务器应用程序…

人工智能聊天机器人与大型语言模型 (LLM):哪个适合您的业务?

简介&#xff1a;欢迎来到未来 您可能听说过人工智能聊天机器人和大型语言模型 (LLM)&#xff0c;对吧&#xff1f; 这些技术奇迹正在重塑企业的沟通和运营方式。 但是&#xff0c;这是一个价值百万美元的问题&#xff1a;哪一个适合您的业务&#xff1f; 让我们深入了解一下&…

【C++航海王:追寻罗杰的编程之路】queue

目录 1 -> queue的介绍和使用 1.1 -> queue的介绍 1.2 -> queue的使用 1.3 -> queue的模拟实现 1 -> queue的介绍和使用 1.1 -> queue的介绍 queue的文档介绍 1. 队列是一种容器适配器&#xff0c;专门用于在FIFO(先进先出)上下文中操作&#xff0c;其…

力扣刷题31-33(力扣 0024/0070/0053)

今日题目&#xff1a; 24. 两两交换链表中的节点 题目&#xff1a;给你一个链表&#xff0c;两两交换其中相邻的节点&#xff0c;并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题&#xff08;即&#xff0c;只能进行节点交换&#xff09; 思路&…

Linux离线安装Docker-Oracle_11g

拉取oracle11g镜像 docker pull registry.cn-hangzhou.aliyuncs.com/helowin/oracle_11g创建11g容器 docker run -d -p 1521:1521 --name oracle11g registry.cn-hangzhou.aliyuncs.com/helowin/oracle_11g查看容器是否创建成功 docker ps -a导出oracle容器&#xff0c;查看…

深入探索MySQL高阶查询语句的艺术与实践

目录 引言 一、条件查询 &#xff08;一&#xff09;比较运算符查询 1.使用匹配符号查询 2.范围查找 &#xff08;二&#xff09;逻辑运算符 二、关键字排序 三、分组与聚合函数 四、限制查询 五、别名 &#xff08;一&#xff09;设置列别名 &#xff08;二&#x…

YoloV5改进策略:Block改进|ECA-Net:用于深度卷积神经网络的高效通道注意力|ECA+压缩膨胀Block实现涨点(独家原创)

摘要 本文使用ECA-Net注意力机制配合压缩膨胀的Block实现涨点。涨点方法是我自己独创的&#xff0c;改进方法简单易用&#xff0c;方便大家用于论文的改进。 论文&#xff1a;《ECA-Net&#xff1a;用于深度卷积神经网络的高效通道注意力》 arxiv.org/pdf/1910.03151.pdf 最…

后端系统开发之——功能完善

原文地址&#xff1a;https://blog.yiming1234.cn/?p830 下面是正文内容&#xff1a; 前言 通过SpringBoot开发用户模块的部分也就差不多要结束了&#xff0c;这一片文章就主要提一些在系统开发中需要注意到的细节部分和功能&#xff0c;也就是剩余的部分。 但是这个专栏只介…

安达发|电子产品制造企业APS生产排程软件

在电子脉动的世界中&#xff0c;时间是芯片上的电流&#xff0c;效率是电路板上的速度。在这个时代&#xff0c;每一微秒都蕴藏着无限可能&#xff0c;每一决策都关乎着企业的生死存亡。APS生产排程软件&#xff0c;是您的电子制造帝国中的智慧大脑&#xff0c;以卓越的创造力&…