当前位置: 首页 > news >正文

【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++的 拷贝赋值运算符函数

&#x1f601;博客主页&#x1f601;&#xff1a;&#x1f680;https://blog.csdn.net/wkd_007&#x1f680; &#x1f911;博客内容&#x1f911;&#xff1a;&#x1f36d;嵌入式开发、Linux、C语言、C、数据结构、音视频&#x1f36d; ⏰发布时间⏰&#xff1a;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框架中&#xff0c;视图类&#xff08;Class-based views&#xff0c;简称CBVs&#xff09;提供了一个面向对象的方式来定义视图。这种方式可以让你通过创建类来组织视图逻辑&#xff0c;而不是使用基于函数的视图&#xff08;Function-based views&#xff0c;简称FBV…...

【Java面试】十七、并发篇(上)

文章目录 1、synchronized关键字的底层原理&#xff1a;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是一个近实时的搜索平台。这意味着&#xff0c;从索引一个文档直到这个文档能够被搜索到有一个很小的延迟&#xff08;通常是一秒&#xff09; 集群 一个集群就是由一个或多个节点组织在一起&#xff0c; 它们共同持有你全部的数据&#x…...

全新抖音快手小红书视频解析去水印系统网站源码

这个系统支持几十种平台&#xff0c;包括抖音、快手小红书以及其他热门社交媒体平台。它可以帮助轻松地下载这些平台上的任何视频&#xff0c;并去除其中的水印&#xff0c;让你可以自由地保存和分享这些视频。 使用方法&#xff1a; 上传压缩包解压&#xff0c;网站信息在inc…...

图解 Python 编程(12) | 文件和编码方式

&#x1f31e;欢迎来到Python 的世界 &#x1f308;博客主页&#xff1a;卿云阁 &#x1f48c;欢迎关注&#x1f389;点赞&#x1f44d;收藏⭐️留言&#x1f4dd; &#x1f31f;本文由卿云阁原创&#xff01; &#x1f4c6;首发时间&#xff1a;&#x1f339;2024年6月9日&am…...

CSDN个人主页动态地图(前端/后端)

前段时间有人问我&#xff0c;关于CSDN个人主页动态地图的实现&#xff0c;我来解答一下。 这里要注意一下&#xff1a;使用CSDN的API需要遵循其开发者协议和使用规范&#xff0c;确保你的使用方式符合相关规定 前端部分&#xff1a; 创建一个HTML页面作为个人主页。在页面上放…...

GUI编程-01

组件 窗口 弹窗 面板 文本框 列表框 按钮 图片 监听事件 鼠标 键盘事件 破解工具 Java提供了丰富的图形用户界面&#xff08;Graphics User Interface&#xff0c;GUI&#xff09;的类库&#xff0c;基于这些类库可以编写窗口程序。 Java关于图形界面的类库主要放在…...

Linux网络-自定义协议、序列化和反序列化、网络计算服务器的实现和Windows端客户端

文章目录 前言一、自定义协议传结构体对象 序列化和反序列化什么是序列化&#xff1f;反序列化 二、计算器服务端&#xff08;线程池版本&#xff09;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的一个数据仓库工具&#xff0c;可以将结构化的数据文件映射为一张数据库表&#xff0c;并提供类SQL查询功能。 其本质是将SQL转换为MapReduce/Spark的任务进行运算&#xff0c;底层由HDFS来提供数据的存储&#xff0c;说白了h…...

三大网络简介

一、三大网是哪三大网 三大网络为电话网、电视广播网、互联网&#xff0c;如果这三大网络使用都是“ip分组交换”技术的话&#xff0c;他们将会被融合成为一个网络&#xff0c; 但是由于历史原因&#xff0c;他们使用了不同的通信技术&#xff0c;三大网各自拥有相当的独立性&a…...

Element-UI全面入门与实战技巧

本文详细介绍了Element-UI的安装、配置、组件使用、布局技巧、交互设计、表单处理、主题定制等内容&#xff0c;旨在帮助开发者快速掌握Element-UI&#xff0c;并能在实际项目中灵活应用。 文章目录 一、Element-UI概述与安装1.1 Element-UI简介1.2 环境搭建1.3 安装Element-UI…...

第103天: 权限提升-Linux 系统辅助项目脏牛Dirty内核漏洞SUIDGUID

项目下载地址 综合类探针&#xff1a; https://github.com/liamg/traitor 自动化提权&#xff1a; https://github.com/AlessandroZ/BeRoot 信息收集&#xff1a; https://github.com/rebootuser/LinEnum https://github.com/sleventyeleven/linuxprivchecker 漏洞探针&#xf…...

如何用群晖当异地组网服务器?

在当今信息化时代&#xff0c;远程通信成为了企业和个人之间不可或缺的一部分。特别是对于跨地区的通信需求&#xff0c;一个可靠的异地组网服务器是必不可少的。而群晖&#xff08;Synology&#xff09;作为一款功能强大的网络存储设备&#xff0c;可以被用作办公室或家庭的异…...

文件怎么去重?5个技巧,教你删除重复文件!

一般来说&#xff0c;在处理大量文件时&#xff0c;你可能会遇到重复的类似文件。这些文件占据了电脑上不必要的磁盘空间&#xff0c;导致系统性能下降。而这些文件可以是不同类型的&#xff0c;如照片、视频、音频、存档、文档等。正因如此&#xff0c;您需要通过文件去重来删…...

标准发布实施 | 《村镇污水处理一体化集成装备技术规范》

根据《中华人民共和国标准化法》以及国家标准化管理委员会、民政部联合制定的《团体标准管理规定》&#xff0c;依据全国团体标准信息平台和《中华环保联合会团体标准管理办法&#xff08;试行&#xff09;》&#xff0c;全国团体标准《村镇污水处理一体化集成装备技术指南》&a…...

人工智能--教育领域的运用

文章目录 &#x1f40b;引言 &#x1f40b;个性化学习 &#x1f988;体现&#xff1a; &#x1f988;技术解析&#xff1a; &#x1f40b;智能辅导与虚拟助手 &#x1f988;体现&#xff1a; &#x1f988;技术解析&#xff1a; &#x1f40b;自动评分与评估 &#x1f…...

【设计模式深度剖析】【3】【行为型】【职责链模式】| 以购物中心客户服务流程为例加深理解

&#x1f448;️上一篇:命令模式 | 下一篇:策略模式&#x1f449;️ 设计模式-专栏&#x1f448;️ 文章目录 职责链模式定义英文原话直译如何理解呢&#xff1f; 职责链模式的角色1. Handler&#xff08;抽象处理者&#xff09;2. ConcreteHandler&#xff08;具体处理者…...

评价GPT-4的方案

评价GPT-4的方案 引言: 随着人工智能技术的不断发展,自然语言处理领域取得了显著的突破。其中,GPT-4作为最新的大型语言模型之一,备受关注。本方案旨在对GPT-4进行全面评价,包括其技术特点、性能表现、应用场景以及潜在的影响等方面。 一、技术特点 1. 模型规模和参数数…...

基于距离变化能量开销动态调整的WSN低功耗拓扑控制开销算法matlab仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.算法仿真参数 5.算法理论概述 6.参考文献 7.完整程序 1.程序功能描述 通过动态调整节点通信的能量开销&#xff0c;平衡网络负载&#xff0c;延长WSN生命周期。具体通过建立基于距离的能量消耗模型&am…...

中南大学无人机智能体的全面评估!BEDI:用于评估无人机上具身智能体的综合性基准测试

作者&#xff1a;Mingning Guo, Mengwei Wu, Jiarun He, Shaoxian Li, Haifeng Li, Chao Tao单位&#xff1a;中南大学地球科学与信息物理学院论文标题&#xff1a;BEDI: A Comprehensive Benchmark for Evaluating Embodied Agents on UAVs论文链接&#xff1a;https://arxiv.…...

Golang dig框架与GraphQL的完美结合

将 Go 的 Dig 依赖注入框架与 GraphQL 结合使用&#xff0c;可以显著提升应用程序的可维护性、可测试性以及灵活性。 Dig 是一个强大的依赖注入容器&#xff0c;能够帮助开发者更好地管理复杂的依赖关系&#xff0c;而 GraphQL 则是一种用于 API 的查询语言&#xff0c;能够提…...

【项目实战】通过多模态+LangGraph实现PPT生成助手

PPT自动生成系统 基于LangGraph的PPT自动生成系统&#xff0c;可以将Markdown文档自动转换为PPT演示文稿。 功能特点 Markdown解析&#xff1a;自动解析Markdown文档结构PPT模板分析&#xff1a;分析PPT模板的布局和风格智能布局决策&#xff1a;匹配内容与合适的PPT布局自动…...

数据链路层的主要功能是什么

数据链路层&#xff08;OSI模型第2层&#xff09;的核心功能是在相邻网络节点&#xff08;如交换机、主机&#xff09;间提供可靠的数据帧传输服务&#xff0c;主要职责包括&#xff1a; &#x1f511; 核心功能详解&#xff1a; 帧封装与解封装 封装&#xff1a; 将网络层下发…...

ElasticSearch搜索引擎之倒排索引及其底层算法

文章目录 一、搜索引擎1、什么是搜索引擎?2、搜索引擎的分类3、常用的搜索引擎4、搜索引擎的特点二、倒排索引1、简介2、为什么倒排索引不用B+树1.创建时间长,文件大。2.其次,树深,IO次数可怕。3.索引可能会失效。4.精准度差。三. 倒排索引四、算法1、Term Index的算法2、 …...

Caliper 配置文件解析:config.yaml

Caliper 是一个区块链性能基准测试工具,用于评估不同区块链平台的性能。下面我将详细解释你提供的 fisco-bcos.json 文件结构,并说明它与 config.yaml 文件的关系。 fisco-bcos.json 文件解析 这个文件是针对 FISCO-BCOS 区块链网络的 Caliper 配置文件,主要包含以下几个部…...

SAP学习笔记 - 开发26 - 前端Fiori开发 OData V2 和 V4 的差异 (Deepseek整理)

上一章用到了V2 的概念&#xff0c;其实 Fiori当中还有 V4&#xff0c;咱们这一章来总结一下 V2 和 V4。 SAP学习笔记 - 开发25 - 前端Fiori开发 Remote OData Service(使用远端Odata服务)&#xff0c;代理中间件&#xff08;ui5-middleware-simpleproxy&#xff09;-CSDN博客…...

Python竞赛环境搭建全攻略

Python环境搭建竞赛技术文章大纲 竞赛背景与意义 竞赛的目的与价值Python在竞赛中的应用场景环境搭建对竞赛效率的影响 竞赛环境需求分析 常见竞赛类型&#xff08;算法、数据分析、机器学习等&#xff09;不同竞赛对Python版本及库的要求硬件与操作系统的兼容性问题 Pyth…...

DAY 26 函数专题1

函数定义与参数知识点回顾&#xff1a;1. 函数的定义2. 变量作用域&#xff1a;局部变量和全局变量3. 函数的参数类型&#xff1a;位置参数、默认参数、不定参数4. 传递参数的手段&#xff1a;关键词参数5 题目1&#xff1a;计算圆的面积 任务&#xff1a; 编写一…...