【C++ | 拷贝赋值运算符函数】一文了解C++的 拷贝赋值运算符函数
😁博客主页😁:🚀https://blog.csdn.net/wkd_007🚀
🤑博客内容🤑:🍭嵌入式开发、Linux、C语言、C++、数据结构、音视频🍭
⏰发布时间⏰:2024-06-09 16:06:48
本文未经允许,不得转发!!!
目录
- 🎄一、为什么需要 赋值运算符函数
- 🎄二、什么是 赋值运算符函数
- 🎄三、使用 赋值运算符函数
- 🎄四、默认的 赋值运算符函数
- 🎄五、总结
🎄一、为什么需要 赋值运算符函数
如果使用一个同类型对象给当前对象赋值,会调用这个类的赋值运算符函数,而默认的赋值运算符函数只进行浅拷贝,可能无法满足一些类的需求,所以需要自定义赋值运算符函数。
下面例子,演示默认的赋值运算符函数存在的问题:
// g++ 12_Operator=_Date.cpp
#include <iostream>
#include <stdio.h>using namespace std;class CDate
{
public:CDate(){} // 无参构造CDate(int year, int mon, int day); // 构造函数声明CDate(const CDate& date); // 拷贝构造函数声明~CDate(); // 析构函数声明void show(){//cout << "Date: " << m_year << "." << m_mon << "." << m_day << endl;cout << "Date: " << str << endl;}private:int m_year;int m_mon;int m_day;char *str;
};// 构造函数定义
CDate::CDate(int year, int mon, int day)
{m_year = year;m_mon = mon;m_day = day;str = new char[64];sprintf(str, "%4d.%02d.%02d", year,mon,day);cout << "Calling Constructor" << ", this=" << this <<endl;
}// 拷贝构造函数定义
CDate::CDate(const CDate& date)
{m_year = date.m_year;m_mon = date.m_mon;m_day = date.m_day;str = new char[64];sprintf(str, "%4d.%02d.%02d", m_year,m_mon,m_day);cout << "Calling Copy Constructor" << ", this=" << this <<endl;
}// 析构函数定义
CDate::~CDate()
{cout << "Calling Destructor" << ", this=" << this <<endl;delete [] str;
}int main()
{CDate date_1(2024,06,05);CDate date_2;date_2=date_1; // 调用默认赋值运算符 2024-06-09 13:39:05return 0;
}
运行结果,因为默认赋值运算符只进行浅拷贝,直接复制了date_1的str指针的值,但是两个对象销毁时,却delete了两次str,导致double free
:
清楚问题之后,我们学习一下怎样声明、定义自己的拷贝赋值运算符函数来规避这个问题。
🎄二、什么是 赋值运算符函数
赋值运算符函数 是重载运算符的一种,关于重载运算符,后面会用其他文章来解释,总之赋值运算符函数的本质也是类成员函数。关于 赋值运算符函数,我们需要了解它是什么时候调用的,其函数原型是怎样的,怎样声明、定义自己的赋值运算符函数。
ANSI C 允许结构赋值, 而 C++允许类对象赋值, 这是通过自动为类重载赋值运算符实现的。这种运算符的原型如下:
类类型 & 类名:operator=(const 类类型 &);
CDate & CDate:operator=(const CDate &); // CDate 类的赋值运算符
怎样声明、定义自己的赋值运算符函数,有下面几个注意点:
1、赋值运算符函数的名称是operator=
,其中operator
是C++的关键字,专门用于重载运算符。
2、赋值运算符函数只允许一个参数,且是该类对象的引用,const表示不会修改该对象的内容。
3、赋值运算符函数返回值类型是该类对象的引用,一般不使用const修饰,这样可以支持连续赋值date1=date2=date3
。
4、赋值运算符函数在实现时应当避免将对象赋给自身,可以判断对象地址来实现this==&date
。
5、如果存在new分配的内容,需要先释放旧的内存
下面以CDate为例,演示声明、定义自己的 赋值运算符函数:
// 在类中声明,下面隐藏了类的其他代码
class CDate
{
public:...CDate& operator=(const CDate& date);// 赋值运算符函数声明...
};// 赋值运算符函数定义
CDate& CDate::operator=(const CDate& date)
{if(this == &date) // 赋值给自身return *this;delete [] str; // 释放旧的数据m_year = date.m_year;m_mon = date.m_mon;m_day = date.m_day;str = new char[64];sprintf(str, "%4d.%02d.%02d", m_year,m_mon,m_day);cout << "Calling operator=" << ", this=" << this <<endl;return *this;
}
🎄三、使用 赋值运算符函数
知道了怎样声明、定义自己的赋值运算符函数后。这一小节,了解何时使用 赋值运算符函数。
将已有的对象赋值给另一个对象时,就会调用 赋值运算符函数。而使用赋值号(=)给对象初始化时则可能调用拷贝构造函数。
这里有两种情况,一种是赋值(对象之前就定义好了),一种是初始化(正在定义某个对象,对象前带有类型)。
下面是a赋值给b:
int a=0;
int b;
b = a; // a赋值给b
下面是使用a的值给b初始化:
int a=0;
int b=a; // 用a的值给b初始化
下面代码演示了怎么声明、定义、使用赋值运算符函数:
// g++ 12_Operator=_Date.cpp
#include <iostream>
#include <stdio.h>using namespace std;class CDate
{
public:CDate() // 无参构造{m_year = m_mon = m_day = 0;str = NULL;} CDate(int year, int mon, int day); // 构造函数声明CDate(const CDate& date); // 拷贝构造函数声明~CDate(); // 析构函数声明CDate& operator=(const CDate& date);// 赋值运算符函数声明void show(){//cout << "Date: " << m_year << "." << m_mon << "." << m_day << endl;cout << "Date: " << str << endl;}private:int m_year;int m_mon;int m_day;char *str;
};// 构造函数定义
CDate::CDate(int year, int mon, int day)
{m_year = year;m_mon = mon;m_day = day;str = new char[64];sprintf(str, "%4d.%02d.%02d", year,mon,day);cout << "Calling Constructor" << ", this=" << this <<endl;
}// 拷贝构造函数定义
CDate::CDate(const CDate& date)
{m_year = date.m_year;m_mon = date.m_mon;m_day = date.m_day;str = new char[64];sprintf(str, "%4d.%02d.%02d", m_year,m_mon,m_day);cout << "Calling Copy Constructor" << ", this=" << this <<endl;
}// 析构函数定义
CDate::~CDate()
{cout << "Calling Destructor" << ", this=" << this <<endl;delete [] str;
}// 赋值运算符函数定义
CDate& CDate::operator=(const CDate& date)
{if(this == &date) // 赋值给自身return *this;delete [] str; // 释放旧的数据m_year = date.m_year;m_mon = date.m_mon;m_day = date.m_day;str = new char[64];sprintf(str, "%4d.%02d.%02d", m_year,m_mon,m_day);cout << "Calling operator=" << ", this=" << this <<endl;return *this;
}int main()
{CDate date_1(2024,06,05);CDate date_2, date_3;date_3 = date_2=date_1; // 调用赋值运算符函数 2024-06-09 15:00:36return 0;
}
运行结果如下:
🎄四、默认的 赋值运算符函数
与处理拷贝构造函数一样,如果一个类末定义自己的拷贝赋值运算符函数,编译器会为它生成一个合成拷贝赋值运算符(synthesized copy-assignment operator)。
合成的拷贝构造函数会逐个复制非静态成员( 成员复制也称为浅复制)的值到目标对象中。根据成员类型有下面几种情况:
1、如果成员是内置类型,则直接复制;
2、如果成员本身就是类对象,则将使用这个类的拷贝构造函数来复制类对象;
3、如果成员是数组,默认的拷贝构造函数会逐元素地拷贝一个数组类型的成员。
禁用赋值
在C++11的标准中,可以在声明赋值运算符时,在函数参数的右括号后面加=delete
,来禁用该类对象的赋值操作,以CDate
为例,加了=delete
的赋值运算符函数声明如下:CDate& operator=(const CDate& date) =delete;// 赋值运算符函数声明
有了这个声明后,就不能给CDate对象赋值了。
🎄五、总结
👉本文主要介绍了C++的拷贝赋值运算符,了解为什么需要拷贝赋值运算符,什么是拷贝赋值运算符,怎样声明、定义、使用拷贝赋值运算符,最后介绍默认的拷贝赋值运算符以及禁用赋值功能。
如果文章有帮助的话,点赞👍、收藏⭐,支持一波,谢谢 😁😁😁
相关文章:
【C++ | 拷贝赋值运算符函数】一文了解C++的 拷贝赋值运算符函数
😁博客主页😁:🚀https://blog.csdn.net/wkd_007🚀 🤑博客内容🤑:🍭嵌入式开发、Linux、C语言、C、数据结构、音视频🍭 ⏰发布时间⏰:2024-06-09 1…...
Linux网络安全
文章目录 一、网络安全概述二、常用服务端口三、 ping命令的使用3.1、ping命令的简单概述3.2、ping命令的使用 四、资源限制4.1、查看系统资源限制4.2、临时修改资源限制4.3、永久修改资源限制 五、网络安全服务工具介绍5.1、ClamAV5.2、Nmap5.3、Wireshark5.4、Netcat5.5、Sno…...
Django 视图类
在Django框架中,视图类(Class-based views,简称CBVs)提供了一个面向对象的方式来定义视图。这种方式可以让你通过创建类来组织视图逻辑,而不是使用基于函数的视图(Function-based views,简称FBV…...
【Java面试】十七、并发篇(上)
文章目录 1、synchronized关键字的底层原理:Monitor2、synchronized相关2.1 为什么说synchronized是重量级锁2.2 synchronized锁升级之偏向锁2.3 synchronized锁升级之轻量级锁 3、Java内存模型JMM4、CAS4.1 CAS流程4.2 CAS底层实现 5、volatile关键字的理解5.1 可见…...
七天进阶elasticsearch[one]
elasticSearch 概述 Elasticsearch是一个近实时的搜索平台。这意味着,从索引一个文档直到这个文档能够被搜索到有一个很小的延迟(通常是一秒) 集群 一个集群就是由一个或多个节点组织在一起, 它们共同持有你全部的数据&#x…...
全新抖音快手小红书视频解析去水印系统网站源码
这个系统支持几十种平台,包括抖音、快手小红书以及其他热门社交媒体平台。它可以帮助轻松地下载这些平台上的任何视频,并去除其中的水印,让你可以自由地保存和分享这些视频。 使用方法: 上传压缩包解压,网站信息在inc…...
图解 Python 编程(12) | 文件和编码方式
🌞欢迎来到Python 的世界 🌈博客主页:卿云阁 💌欢迎关注🎉点赞👍收藏⭐️留言📝 🌟本文由卿云阁原创! 📆首发时间:🌹2024年6月9日&am…...
CSDN个人主页动态地图(前端/后端)
前段时间有人问我,关于CSDN个人主页动态地图的实现,我来解答一下。 这里要注意一下:使用CSDN的API需要遵循其开发者协议和使用规范,确保你的使用方式符合相关规定 前端部分: 创建一个HTML页面作为个人主页。在页面上放…...
GUI编程-01
组件 窗口 弹窗 面板 文本框 列表框 按钮 图片 监听事件 鼠标 键盘事件 破解工具 Java提供了丰富的图形用户界面(Graphics User Interface,GUI)的类库,基于这些类库可以编写窗口程序。 Java关于图形界面的类库主要放在…...
Linux网络-自定义协议、序列化和反序列化、网络计算服务器的实现和Windows端客户端
文章目录 前言一、自定义协议传结构体对象 序列化和反序列化什么是序列化?反序列化 二、计算器服务端(线程池版本)1.main.cc2.Socket.hpp3.protocol.hpp4.Calculator.hpp5.serverCal.hpp6.threadPool.hpp7.Task.hpp8. log.hpp 客户端Windows客…...
Hive知识体系保姆级教程
一. Hive概览 1.1 hive的简介 Hive是基于Hadoop的一个数据仓库工具,可以将结构化的数据文件映射为一张数据库表,并提供类SQL查询功能。 其本质是将SQL转换为MapReduce/Spark的任务进行运算,底层由HDFS来提供数据的存储,说白了h…...
三大网络简介
一、三大网是哪三大网 三大网络为电话网、电视广播网、互联网,如果这三大网络使用都是“ip分组交换”技术的话,他们将会被融合成为一个网络, 但是由于历史原因,他们使用了不同的通信技术,三大网各自拥有相当的独立性&a…...
Element-UI全面入门与实战技巧
本文详细介绍了Element-UI的安装、配置、组件使用、布局技巧、交互设计、表单处理、主题定制等内容,旨在帮助开发者快速掌握Element-UI,并能在实际项目中灵活应用。 文章目录 一、Element-UI概述与安装1.1 Element-UI简介1.2 环境搭建1.3 安装Element-UI…...
第103天: 权限提升-Linux 系统辅助项目脏牛Dirty内核漏洞SUIDGUID
项目下载地址 综合类探针: https://github.com/liamg/traitor 自动化提权: https://github.com/AlessandroZ/BeRoot 信息收集: https://github.com/rebootuser/LinEnum https://github.com/sleventyeleven/linuxprivchecker 漏洞探针…...
如何用群晖当异地组网服务器?
在当今信息化时代,远程通信成为了企业和个人之间不可或缺的一部分。特别是对于跨地区的通信需求,一个可靠的异地组网服务器是必不可少的。而群晖(Synology)作为一款功能强大的网络存储设备,可以被用作办公室或家庭的异…...
文件怎么去重?5个技巧,教你删除重复文件!
一般来说,在处理大量文件时,你可能会遇到重复的类似文件。这些文件占据了电脑上不必要的磁盘空间,导致系统性能下降。而这些文件可以是不同类型的,如照片、视频、音频、存档、文档等。正因如此,您需要通过文件去重来删…...
标准发布实施 | 《村镇污水处理一体化集成装备技术规范》
根据《中华人民共和国标准化法》以及国家标准化管理委员会、民政部联合制定的《团体标准管理规定》,依据全国团体标准信息平台和《中华环保联合会团体标准管理办法(试行)》,全国团体标准《村镇污水处理一体化集成装备技术指南》&a…...
人工智能--教育领域的运用
文章目录 🐋引言 🐋个性化学习 🦈体现: 🦈技术解析: 🐋智能辅导与虚拟助手 🦈体现: 🦈技术解析: 🐋自动评分与评估 …...
【设计模式深度剖析】【3】【行为型】【职责链模式】| 以购物中心客户服务流程为例加深理解
👈️上一篇:命令模式 | 下一篇:策略模式👉️ 设计模式-专栏👈️ 文章目录 职责链模式定义英文原话直译如何理解呢? 职责链模式的角色1. Handler(抽象处理者)2. ConcreteHandler(具体处理者…...
评价GPT-4的方案
评价GPT-4的方案 引言: 随着人工智能技术的不断发展,自然语言处理领域取得了显著的突破。其中,GPT-4作为最新的大型语言模型之一,备受关注。本方案旨在对GPT-4进行全面评价,包括其技术特点、性能表现、应用场景以及潜在的影响等方面。 一、技术特点 1. 模型规模和参数数…...
LeetCode | 1624.两个相同字符之间的最长子字符串
这道题拿到手想法就是去双重遍历暴力解,对于每个字符,从后往前遍历字符串,找到从后往前一直到本次遍历的这个字符串这段子串中和这个字符串相同的字符位置,然后得到子字符串的长度,和ans存储的值做一个比较,…...
【CS.AI】GPT-4o:重新定义人工智能的新标杆
文章目录 1 序言2 GPT-4o的技术亮点3 GPT-4o与前代版本的对比3.1 热门AI模型对比表格GPT-3.5GPT-4GPT-4oBERTT5 3.2 其他 4 个人体验与感受5 结论 1 序言 嘿,大家好!今天要聊聊一个超级酷的AI新突破——GPT-4o!最近,OpenAI发布了…...
野火FPGA跟练(四)——串口RS232、亚稳态
目录 简介接口与引脚通信协议亚稳态RS232接收模块模块框图时序波形RTL 代码易错点Testbench 代码仿真 RS232发送模块模块框图时序波形RTL 代码Testbench 代码仿真 简介 UART:Universal Asynchronous Receiver/Transmitter,异步串行通信接口。发送数据时…...
Qt for Android 申请摄像头权限
步骤 1. 添加用户权限 方式1: AndroidManifest.xml 中新增(不添加后面申请选项时不弹窗) 或者再Qt Creator中直接添加 方式2: .pro 中引用multimedia 模块,编译时配置自动添加 <uses-permission android:name"android.permissi…...
kivy 百词斩项目 报错
AttributeError: FigureCanvasKivyAgg object has no attribute resize_event AttributeError: FigureCanvasKivyAgg object has no attribute resize_event 是一种常见的Python错误,当你试图访问一个对象(在这个例子中是 FigureCanvasKivyAgg 对象&am…...
ChatTTS 文字生成语言本地模型部署
ChatTTS部署 官方信息 [ChatTTS首页](https://chattts.com/)搭建步骤 1、下载源码 git clone https://github.com/2noise/ChatTTS.git 2、按照环境 pip install torch ChatTTS pip install -r requirements.txt 3、下载模型 git clone https://www.modelscope.cn/pzc163/ch…...
多曝光融合算法(三)cv2.createAlignMTB()多曝光图像融合的像素匹配问题
文章目录 1.cv2.createAlignMTB() 主要是计算2张图像的位移,假设位移移动不大2.多曝光图像的aline算法:median thresold bitmap原理讲解3.图像拼接算法stitch4.多曝光融合工具箱 1.cv2.createAlignMTB() 主要是计算2张图像的位移,假设位移移动…...
C/C++|类型推导中的模式匹配
在C11及以上的相关语法中,特别是在模版元编程的范式里,类型推导是了重中之重。 在 《Effective Modern C 》 中第一章主要就是讲各种类型推导。 当然了,谈到类型推导,我们不得不先搞懂类型推导中的模式匹配,这是基础&a…...
The 18th Northeast Collegiate Programming Contest(5/9/13)
心得 赛中ac:5,目前ac:9,题目总数:13 中档可做题还是很多的,可惜遇到了难绷的queueforces, 最后15min才判出来,oi赛制5wa4遗憾离场,赛后把几个题都给调过了࿰…...
Vue前端在线预览文件插件
Vue前端在线预览文件插件 一、使用场景 1.1.像文档资料等,只想让他人在线预览,但不能下载。此等场景需求可以用到此插件。 二、此文档介绍两种插件 1.view.xdocin插件 (上线后免费几天,然后收费,添加作者后,可以延…...
网站架设 数据库选用/大一html网页制作作业
阿里高级专家手推最新版Spring源码深度解析(第2版)笔记总结 特点: 全面剖析Spring源码,方便读者根据业务需求进行更改或扩展所有知识点秉承由浅入深、由易到难的讲解架构采用抽丝剥茧的方式来阐述复杂的逻辑,降低理解…...
一个新网站要怎么做seo/西部数码域名注册官网
jsp使用jdk8时,需要tomcat7以及以上版本,jsp在使用jdk7的时候,tomcat使用tomcat6即可...
什么网站可以做会计题目/百度应用平台
不称深度指南,只愿浅度指北之前,用 VBA 开发了一个 Excel 插件「浅北表格助手」,随后,也发了两篇关于WordVBA 的教程,后台有小伙伴留言,说希望看到一些偏实用的代码。今天,它来了。我们在写 Wor…...
把名字设计成logo/重庆做网络优化公司电话
今天来用Node.js做一个小小的爬虫项目 爬虫目标:http://songshuhui.net/(科学松鼠会) 我们需要创建一个文件夹,自己命名就好,然后在文件夹里创建两个文件夹分别命名为data和img,进入到这个总文件夹的目录终…...
cms网站开发/怎么样建立自己的网站
例如:var strq1207526854 str.substring(form,to):从字符串里截取下标为form到下标为to的字符串(不包括to对应的字符)alert(str.substring(2,6)) // 2075当form>to时,substring会把较小的参数作为第一参数 al…...
公司做网站怎么样/网站seo批量查询工具
智慧 毅力 无所不能 正确性、健壮性、可靠性、效率、易用性、可读性、可复用性、兼容性、可移植性... Lua和C交互详细总结 转自:http://cn.cocos2d-x.org/tutorial/show?id1474 一、Lua堆栈 要理解Lua和C交互,首先要理解Lua堆栈。 简单来说࿰…...