C++ 重载赋值运算符

在定义的同时进行赋值叫做初始化(Initialization),定义完成以后再赋值(不管在定义的时候有没有赋值)就叫做赋值(Assignment)。初始化只能有一次,赋值可以有多次。

当以拷贝的方式初始化一个对象时,会调用拷贝构造函数;当给一个对象赋值时,会调用重载过的赋值运算符。

即使我们没有显式的重载赋值运算符,编译器也会以默认地方式重载它。默认重载的赋值运算符功能很简单,就是将原有对象的所有成员变量一一赋值给新对象,这和默认拷贝构造函数的功能类似。

对于简单的类,默认的赋值运算符一般就够用了,我们也没有必要再显式地重载它。但是当类持有其它资源时,例如动态分配的内存、打开的文件、指向其他数据的指针、网络连接等,默认的赋值运算符就不能处理了,我们必须显式地重载它,这样才能将原有对象的所有数据都赋值给新对象。

我们以 Array 类为例,该类拥有一个指针成员,指向动态分配的内存。为了让 Array 类的对象之间能够正确地赋值,我们必须重载赋值运算符。请看下面的代码:

#include <iostream>
#include <cstdlib>
using namespace std;//变长数组类
class Array{
public:Array(int len);Array(const Array &arr);  //拷贝构造函数~Array();
public:int operator[](int i) const { return m_p[i]; }  //获取元素(读取)int &operator[](int i){ return m_p[i]; }  //获取元素(写入)Array & operator=(const Array &arr);  //重载赋值运算符int length() const { return m_len; }
private:int m_len;int *m_p;
};Array::Array(int len): m_len(len){m_p = (int*)calloc( len, sizeof(int) );
}Array::Array(const Array &arr){  //拷贝构造函数this->m_len = arr.m_len;this->m_p = (int*)calloc( this->m_len, sizeof(int) );memcpy( this->m_p, arr.m_p, m_len * sizeof(int) );
}Array::~Array(){ free(m_p); }Array &Array::operator=(const Array &arr){  //重载赋值运算符if( this != &arr){  //判断是否是给自己赋值this->m_len = arr.m_len;free(this->m_p);  //释放原来的内存this->m_p = (int*)calloc( this->m_len, sizeof(int) );memcpy( this->m_p, arr.m_p, m_len * sizeof(int) );}return *this;
}//打印数组元素
void printArray(const Array &arr){int len = arr.length();for(int i=0; i<len; i++){if(i == len-1){cout<<arr[i]<<endl;}else{cout<<arr[i]<<", ";}}
}int main(){Array arr1(10);for(int i=0; i<10; i++){arr1[i] = i;}printArray(arr1);Array arr2(5);for(int i=0; i<5; i++){arr2[i] = i;}printArray(arr2);arr2 = arr1;  //调用operator=()printArray(arr2);arr2[3] = 234;  //修改arr1的数据不会影响arr2arr2[7] = 920;printArray(arr1);return 0;
}

运行结果:

0, 1, 2, 3, 4, 5, 6, 7, 8, 9
0, 1, 2, 3, 4
0, 1, 2, 3, 4, 5, 6, 7, 8, 9
0, 1, 2, 3, 4, 5, 6, 7, 8, 9

将 arr1 赋值给 arr2 后,修改 arr2 的数据不会影响 arr1。如果把 operator=() 注释掉,那么运行结果将变为:

0, 1, 2, 3, 4, 5, 6, 7, 8, 9
0, 1, 2, 3, 4
0, 1, 2, 3, 4, 5, 6, 7, 8, 9
0, 1, 2, 234, 4, 5, 6, 920, 8, 9 

去掉operator=()后,由于 m_p 指向的堆内存会被 free() 两次,所以还会导致内存错误。

分析重载过的赋值运算符。

1 operator=() 的返回值类型为Array &,这样不但能够避免在返回数据时调用拷贝构造函数,还能够达到连续赋值的目的。下面的语句就是连续赋值:
arr4 = arr3 = arr2 = arr1;

2 if( this != &arr)语句的作用是「判断是否是给同一个对象赋值」:如果是,那就什么也不做;如果不是,那就将原有对象的所有成员变量一一赋值给新对象,并为新对象重新分配内存。下面的语句就是给同一个对象赋值:

arr1 = arr1;
arr2 = arr2;

3 return *this表示返回当前对象(新对象)。

4 operator=() 的形参类型为const Array &,这样不但能够避免在传参时调用拷贝构造函数,还能够同时接收 const 类型和非 const 类型的实参。

5 赋值运算符重载函数除了能有对象引用这样的参数之外,也能有其它参数。但是其它参数必须给出默认值,例如:

Array & operator=(const Array &arr, int a = 100);

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

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

相关文章

android 扫描重复文件,Android Gradle在APK META-INF中复制的重复文件

我尝试在我的Android应用程序中添加spring但应用程序不运行.我真的不知道为什么我的跑步失败了.你能帮我解决这个问题,谢谢这是我的app / build.gradle配置&#xff1a;apply plugin: com.android.applicationandroid {compileSdkVersion 23buildToolsVersion "23.0.3&quo…

C++ 转换构造函数

在 C/C 中&#xff0c;不同的数据类型之间可以相互转换。无需用户指明如何转换的称为自动类型转换&#xff08;隐式类型转换&#xff09;&#xff0c;需要用户显式地指明如何转换的称为强制类型转换。 自动类型转换示例&#xff1a; int a 6; a 7.5 a;编译器对 7.5 是作为…

android 媒体库扫描,如何扫描出Android系统媒体库中视频文件

Android系统启动时会去扫描系统文件&#xff0c;并将系统支持的视频文件(mp4,3gp,wmv)扫描到媒体库(MediaStore)中&#xff0c;下面代码演示如何获得这些文件的信息&#xff1a;publicstatic List sysVideoList null;// 视频信息集合sysVideoList new ArrayList();setVideoLi…

C++ 四种类型转换运算符

隐式类型转换是安全的&#xff0c;显式类型转换是有风险的&#xff0c;C语言之所以增加强制类型转换的语法&#xff0c;就是为了强调风险&#xff0c;让程序员意识到自己在做什么。 但是&#xff0c;这种强调风险的方式还是比较粗放&#xff0c;粒度比较大&#xff0c;它并没有…

Android leak内存,GitHub - jin870132/memoryleakdemo: 安卓内存泄露几种常见形式及解决方案...

安卓内存泄露几种常见形式及解决方案一.前言1.内存溢出与内存泄露内存溢出(oom)&#xff0c;是指程序在申请内存时&#xff0c;没有足够的内存空间供其使用&#xff0c;出现oom&#xff1b;比如申请了一个integer,但给它存了long才能存下的数&#xff0c;那就是内存溢出。内存泄…

第二批鸿蒙手机排行,鸿蒙系统第二批升级机型有哪些 鸿蒙系统第二批升级机型名单一览...

华为6月2日召开开启鸿蒙发布会&#xff0c;很多华为手机的用户都想第一时间用上鸿蒙手机系统&#xff0c;今天就给大家带来鸿蒙系统第二批升级机型名单一览&#xff0c;一起来看看吧鸿蒙系统第二批升级机型名单一览具体机型&#xff1a;HUAWEI Mate20 SeriesHUAWEl nova 8 Seri…

C++ 异常类型以及多级catch匹配

exceptionType是异常类型&#xff0c;它指明了当前的 catch 可以处理什么类型的异常&#xff1b;variable是一个变量&#xff0c;用来接收异常信息。当程序抛出异常时&#xff0c;会创建一份数据&#xff0c;这份数据包含了错误信息&#xff0c;程序员可以根据这些信息来判断到…

火狐 html5 退出 白屏,Html5+ 后退按钮出现白屏(webView.back会白屏)

您好&#xff0c;打包装到 iPad 上去调试&#xff0c;A ->B 之后&#xff0c;第一次调用 webView.back 会显示白屏&#xff0c;页面切换使用的 webView.loadUrl &#xff0c;代码如下&#xff1a;var sub plus.webview.create(_basePath pages/canlucate/canlucate.html, …

C++ throw

我们知道C 异常处理的流程&#xff0c;具体为&#xff1a; 抛出&#xff08;Throw&#xff09;--> 检测&#xff08;Try&#xff09; --> 捕获&#xff08;Catch&#xff09;异常必须显式地抛出&#xff0c;才能被检测和捕获到&#xff1b;如果没有显式的抛出&#xff0…

html移除click事件绑定,带你了解JQuery中绑定事件(bind())和移除事件(unbind())...

本文主要向大家详细介绍了jQuery的绑定事件和移除事件的使用方法和示例分享&#xff0c;这里推荐给有需要的小伙伴们参考下。有时候事件执行完了&#xff0c;想取消事件的效果可以通过一定的办法来处理。比如bind()(绑定事件)和unbind()(移除通过bind()方法添加的事件)方法来移…

html怎么设计自己的网页,求一份自己设计的简单网页 HTML格式

A&#xff1a;百格*特点&#xff1a;该仪器用于均匀划出一定规格尺寸的方格&#xff0c;通过评定方格内涂膜的完整程度来评定涂膜对基材附着程度&#xff0c;以‘级’表示。它主要用于有机涂料划格法附着力的测定&#xff0c;不仅适用于实验室&#xff0c;也可用于各种条件下的…

VC2010 项目的创建

在VC2010中创建一个项目 1 . 创建新项目。打开我们的VC2010&#xff0c;点工具栏第一个按钮&#xff08;New Project&#xff09;&#xff0c;或者菜单 File -> New -> Project…&#xff0c;或者按快捷键 CtrlShiftN&#xff0c;几种方式都可以。 2 . 在 “New Project…

html5教学案例撰写,怎样撰写教育教学案例

怎样撰写教育教学案例教学是教师的教和学生的学所组成的一种人类特有的人才培养活动。那么&#xff0c;怎样撰写教育教学案例呢?下面是小编收集整理的撰写教育教学案例的相关内容&#xff0c;希望对您有所帮助!1.撰写教育教学案例的思想准备要写好教育、教学案例&#xff0c;首…

error C2143: syntax error : missing ';' before '}'

我们在运行C程序的时候经常会遇到错误&#xff0c;如果你遇到了这个错误&#xff1a;error C2143: syntax error : missing ‘;’ before ‘}’&#xff0c;那麽我将帮你解决这个错误。 错误展示 完整代码 #include <stdio.h> #define exchange(a,b){int t; ta;ab;bt} …

绘制彩虹html代码,HTML5 Canvas 彩虹螺旋图生成器

JavaScript语言&#xff1a;JaveScriptBabelCoffeeScript确定$(function() {var myCanvas, context, width, height;var lines [],numberOfLines 12;var colours [#FFD800, #FF6A00, #FF0000, #0094FF, #0026FF, #4800FF, #7FFF8E, #B6FF00, #4CFF00, #FFFFFF];var Line fu…

VC2010运行C程序时黑框一闪就没

黑框一闪就没如何解决的呢&#xff1f; 首先我们要知道为什么黑框一闪就没 闪一下是因为它执行完输出函数(printf)后直接返回系统了。 解决办法 在程序里加一个system(“pause”)&#xff0c;这个是调用系统函数&#xff0c;到时候会显示"按任意键退出"。 使用方…

厦门大学计算机科学与技术学院考研分数线,2020年厦门大学计算机科学与技术考研经验分享...

原标题&#xff1a;2020年厦门大学计算机科学与技术考研经验分享大家好&#xff0c;我是育明考研小赵老师关于2020年厦门大学计算机科学与技术考研信息汇总&#xff0c;请参考一、院校介绍厦门大学(Xiamen University)&#xff0c;简称厦大(XMU)&#xff0c;是中华人民共和国教…

Redis ops详解

Redis缓存数据库的ops问题 我们使用Java操作Redis数据库的时候&#xff0c;往往会输出和ops相关的内容&#xff0c;下面给大家讲解一下ops相关的内容。 ops是什么&#xff1f; redis中的OPS 即operation per second 每秒操作次数。意味着每秒对Redis的持久化操作。 所以我们…

山东大学继续教育计算机在线作业,山东大学继续教育数文字电子技术基础习题3及答案.docx...

精品文档精品文档PAGEPAGE5精品文档PAGE..数字电子技术基础模拟卷3一填空。1逻辑代数中&#xff0c;基本的运算关系是与、或和非。2十进制数27转换成二进制数为11011&#xff1b;转换成8421BCD码是3在逻辑代数中&#xff0c;AABAB&#xff1b;A1。4同一个逻辑函数可以有不同的逻…

Spring操作Redis

在 Spring 中使用 Redis&#xff0c;除了需要 jedis.jar 外&#xff0c;还需要下载 spring-data-redis.jar&#xff0c;这里值得注意的是 jar 包和 Spring 版本兼容的问题&#xff0c;我使用的 jar 包版本是 1.8.1&#xff0c;而 Spring 的版本是 5.0.4&#xff0c;如果使用其他…