C++ 类和对象中的 拷贝构造 和 运算符重载
构造函数中可以添加参数并添加默认值构成缺省构造,如果我们在构造函数的参数中加上自身类型类的引用和其他给出默认值的参数则会构成一种特殊的构造函数叫做———拷贝构造函数
1.拷贝构造
拷贝构造的特点:
1.拷贝构造函数是构造函数的一个重载
2.拷贝构造函数的参数只有⼀个且必须是类类型对象的引用,使用传值方式编译器直接报错,因为语法逻辑上会引发无穷递归调用
3.C++规定自定义类型对象进行拷贝行为必须调用拷贝构造,所以这里自定义类型传值传参和传值返回都会调用拷贝构造完成
4.若未显式定义拷贝构造,编译器会生成自动生成拷贝构造函数。自动生成的拷贝构造对内置类型成员变量会完成值拷贝/浅拷贝(一个字节一个字节的拷贝),对自定义类型成员变量会调用他的拷贝构造
5.像Date这样的类成员变量全是内置类型且没有指向什么资源,编译器自动生成的拷贝构造就可以完成需要的拷贝,所以不需要我们显示实现拷贝构造。像Stack(栈)这样的类,虽然也都是内置类型,但是其对象指向了资源,编译器自动生成的拷贝构造完成的值拷贝/浅拷贝不符合我们的需求,所以需要我们自己实现深拷贝(对指向的资源也进行拷贝)。像MyQueue(两个栈实现的队列)这样的类型内部主要是自定义类型Stack成员,编译器自动生成的拷贝构造会调用Stack的拷贝构造,也不需要我们显示实现 MyQueue的拷贝构造。这里还有⼀个小技巧,如果一个类显示实现了析构并释放资源,那么他就 需要显示写拷贝构造,否则就不需要
6.传值返回会产生一个临时对象调用拷贝构造,传值引用返回,返回的是返回对象的别名(引用),没 有产生拷贝。但是如果返回对象是一个当前函数局部域的局部对象,函数结束就销毁了,那么使用引用返回是有问题的,这时的引用相当于一个野引用,类似一个野指针一样。传引用返回可以减少拷贝,但是一定要确保返回对象,在当前函数结束后还在,才能用引用返回
例:
#include<iostream>
using namespace std;
class Date
{
public:Date(int year = 2024, int month = 11, int day = 22){_year = year;_month = month;_day = day;}Date(Date& d){_year = d._year;_month = d._month;_day = d._day;}
private:int _year;int _month;int _day;
};
Date& test()
{Date d2(2024, 11, 21);return d2;//d2的作用域只在这个函数里,出了这个函数后就会销毁
}
int main()
{Date d1;Date d3 = test();return 0;
}
在调试此程序时,我们可以通过监视窗口看到以下内容
我们可以看到d3的值是随机值,说明d2并没有被返回
2.运算符重载
(1)运算符重载
1.当运算符被用于类类型的对象时,C++语言允许我们通过运算符重载的形式指定新的含义。C++规定类类型对象使用运算符时,必须转换成调用对应运算符重载,若没有对应的运算符重载,则会编译报错
2.运算符重载是具有特名字的函数,他的名字是由operator和后面要定义的运算符共同构成。和其他函数一样,它也具有其返回类型和参数列表以及函数体
代码1:
#include<iostream>
using namespace std;
class Date
{
public:void Print(){cout << _year << " " << _month << " " << _day << endl;}int GetMonthDay(int year, int month);// 全缺省的构造函数Date(int year = 1900, int month = 1, int day = 1);// 拷贝构造函数// d2(d1)Date(const Date& d){_year = d._year;_month = d._month;_day = d._day;}// 赋值运算符重载//d2 = d3 -> d2.operator=(&d2, d3)Date& operator=(const Date& d);// 析构函数~Date();// 日期+=天数Date& operator+=(int day);// 日期+天数Date operator+(int day);// 日期-天数Date operator-(int day);// 日期-=天数Date& operator-=(int day);// 前置++Date& operator++();// 后置++Date operator++(int);// 后置--Date operator--(int);// 前置--Date& operator--();// >运算符重载bool operator>(const Date& d);// ==运算符重载bool operator==(const Date& d);// >=运算符重载bool operator >= (const Date& d);// <运算符重载bool operator < (const Date& d);// <=运算符重载bool operator <= (const Date& d);// !=运算符重载bool operator != (const Date& d);// 日期-日期 返回天数int operator-(const Date& d);
private:int _year;int _month;int _day;
};
3.重载运算符函数的参数个数和该运算符作用的运算对象数量一样多。一元运算符有一个参数,二元运算符有两个参数,二元运算符的左侧运算对象传给第一个参数,右侧运算对象传给第二个参数
4.如果一个重载运算符函数是成员函数,则它的第一个运算对象默认传给隐式的this指针,因此运算符重载作为成员函数时,参数比运算对象少一个
例如在代码1中我们的Date日期类中,重载运算符函数是它的成员函数,他的参数中是有this指针为第一个参数的,所以在构建重载运算符函数时需注意参数数量
5.运算符重载以后,其优先级和结合性与对应的内置类型运算符保持⼀致——即你构建的重载运算符=和正常的=为相等优先级和结合性
6.不能通过连接语法中没有的符号来创建新的操作符:比如operator@。
7. .* :: sizeof ? : . 注意以上5个运算符不能重载
8.重载操作符至少有一个类类型参数,不能通过运算符重载改变内置类型对象的含义——防止你把正常的加改成减
9.⼀个类需要重载哪些运算符,是看哪些运算符重载后有意义,比如代码1中的Date类重载operator-就有意 义,但是重载operator+就没有意义
10.重载++运算符时,有前置++和后置++,运算符重载函数名都是operator++,无法很好的区分。 C++规定,后置++重载时,增加⼀个int形参,跟前置++构成函数重载,方便区分
11.重载<<和>>时,需要重载为全局函数,因为重载为成员函数,this指针默认抢占了第⼀个形参位置,第⼀个形参位置是左侧运算对象,调用时就变成了对象<<cout,不符合使⽤习惯和可读性。重载为全局函数把ostream/istream放到第⼀个形参位置就可以了,第二个形参位置当类类型对象
流插入
ostream& operator<<(ostream& out, const Date& d)
{out << d._year << "年" << d._month << "月" << d._day << "日" << endl;return out;
}
流提取
istream& operator>>(istream& in, Date& d)
{while (1){cout << "请依次输入年月日:>";in >> d._year >> d._month >> d._day;if (d.CheckDate()){break;}else{cout << "输入的日期非法,请重新输入" << endl;}}return in;
}
(2)赋值运算符重载
赋值运算符重载是一个默认成员函数,用于完成两个已经存在的对象直接的拷贝赋值,这里要注意跟拷贝构造区分,拷贝构造用于一个对象拷贝初始化给另一个要创建的对象
1.赋值运算符重载是一个运算符重载,规定必须重载为成员函数。赋值运算重载的参数建议写成 const当前类类型引用,否则会传值传参会有拷贝
class Date
{
public:Date(int year=2024,int month =11,int day=22){_year=year;_month=month;_day=day;}
private:int _year;int _month;int _day;
};
int main()
{Date d1(2024,11,22);Date d2(2024,11,21);d1=d2;//赋值运算符重载Date d3=d2;//拷贝构造return 0;
}
2.有返回值,且建议写成当前类类型引用,引用返回可以提高效率,有返回值目的是为了支持连续赋值场景
3.没有显式实现时,编译器会自动生成⼀个默认赋值运算符重载,默认赋值运算符重载行为跟默认构造函数类似,对内置类型成员变量会完成值拷贝/浅拷贝(一个字节一个字节的拷贝),对自定义类型成员变量会调用他的拷贝构造
4.像Date这样的类成员变量全是内置类型且没有指向什么资源,编译器自动生成的赋值运算符重载就可以完成需要的拷贝,所以不需要我们显示实现赋值运算符重载。像Stack这样的类,虽然也都是内置类型,但是指向了资源,编译器自动生成的赋值运算符重载完成的值拷贝/浅拷贝不符合我 们的需求,所以需要我们自己实现深拷贝(对指向的资源也进行拷贝)。像MyQueue这样的类型内部 主要是自定义类型Stack成员,编译器自动生成的赋值运算符重载会调用Stack的赋值运算符重载, 也不需要我们显示实现MyQueue的赋值运算符重载。这里还有一个小技巧,如果一个类显示实现了析构并释放资源,那么他就需要显示写赋值运算符重载,否则就不需要
相关文章:

C++ 类和对象中的 拷贝构造 和 运算符重载
构造函数中可以添加参数并添加默认值构成缺省构造,如果我们在构造函数的参数中加上自身类型类的引用和其他给出默认值的参数则会构成一种特殊的构造函数叫做———拷贝构造函数 1.拷贝构造 拷贝构造的特点: 1.拷贝构造函数是构造函数的一个重载 2.拷…...
el-table最大高度无法滚动
解决el-table同时使用fixed和计算的最大高度时固定右边的列无法跟随滚动的问题 原因:el-table组件会根据传入的 max-height 计算表格内容部分 和 fixed部分的最大高度,以此来生成滚动条和产生滚动效果,当传入的 max-height 为一个计算的高度…...

Vscode写markdown快速插入python代码
如图当我按下快捷键CRTLSHIFTK 自动出现python代码片段 配置方法shortcuts’ 打开这个json文件 输入 {"key": "ctrlshiftk","command": "editor.action.insertSnippet","when": "editorTextFocus","args&…...

基于 NCD 与优化函数结合的非线性优化 PID 控制
基于 NCD 与优化函数结合的非线性优化 PID 控制 1. 引言 NCD(Normalized Coprime Factorization Distance)优化是一种用于非线性系统的先进控制方法。通过将 NCD 指标与优化算法结合,可以在动态调整控制参数的同时优化控制器性能。此方法特别…...
【数据分析】基于GEE实现大津算法提取洞庭湖流域水体
大津算法提取水体 1.写在前面2.洞庭湖水体识别1.写在前面 最大类间方差法,也称为Otsu或大津法,是一种高效的图像二值化算法,由日本学者Otsu于1979年提出。该算法基于图像的频率分布直方图,假设图像包含两类像素(前景和背景),并计算出一个最佳阈值,以最大化类间方差,从…...

计算机网络安全 —— 报文摘要算法 MD5
一、报文摘要算法基本概念 使用加密通常可达到报文鉴别的目的,因为伪造的报文解密后一般不能得到可理解的内容。但简单采用这种方法,计算机很难自动识别报文是否被篡改。另外,对于不需要保密而只需要报文鉴别的网络应用,对整个…...
LeetCode 746. 使用最小花费爬楼梯 java题解
https://leetcode.cn/problems/min-cost-climbing-stairs/description/ 优化:可以不用dp数组,用变量,节省空间。 class Solution {public int minCostClimbingStairs(int[] cost) {int lencost.length;int[] dpnew int[len1];dp[0]0;//爬到0…...

Kubernetes的pod控制器
文章目录 一,什么是pod控制器二,pod控制器类型(重点)1.ReplicaSet2.Deployment3.DaemonSet4.StatefulSet5.Job6.Cronjob 三,pod与控制器的关系1.Deployment2.SatefulSet2.1StatefulSet组成2.2headless的由来2.3有状态服…...

ArcMap 处理栅格数据地形图配准操作
ArcMap 处理栅格数据地形图配准操作今天分享 一、地形图配准 1、绘图 点击 开始绘制,四条线 2、地理配准 1)点击弹出 2)画控制点 关闭自动校正 画线 从焦点向外划线,然后邮件输入坐标弹出框,填写相应内容,…...
comprehension
1.读题---猜---文章主题 只读题目,不读选项 2.文章--定位 3.用文章对应选项 1 be based on be dependent upon 2 fruitful adj.富有成效的;硕果累累的; 3 unfruitful adj.徒然的,无益的,没有结果的 4 desperately adv.拼命地&#x…...
开源宝藏:Smart-Admin 重复提交防护的 AOP 切面实现详解
首先,说下重复提交问题,基本上解决方案,核心都是根据URL、参数、token等,有一个唯一值检验是否重复提交。 而下面这个是根据用户id,唯一值进行判定,使用两种缓存方式,redis和caffeineÿ…...
使用 npm 安装 Electron 作为开发依赖
好的,下面是一个使用 npm pack 和 npm install 命令来打包和安装离线版本的 npm 包的具体示例。我们将以 electron 为例,演示如何在有网络连接的机器上打包 electron,然后在没有网络连接的机器上安装它。 步骤 1: 在有网络连接的机器上打包 …...

JavaWeb之综合案例
前言 这一节讲一个案例 1. 环境搭建 然后就是把这些数据全部用到sql语句中执行 2.查询所有-后台&前台 我们先写后台代码 2.1 后台 2.2 Dao BrandMapper: 注意因为数据库里面的名称是下划线分割的,我们类里面是驼峰的,所以要映射 …...
MySQL 报错:1137 - Can‘t reopen table
MySQL 报错:1137 - Can’t reopen table 1. 问题 对临时表查询: select a.ts_code,a.tsnum,b.tsnum from (select t.ts_code ,count(*) tsnum from tmp_table t group by t.ts_code having count(*) > 20 and count(*)< 50 ) a ,(select t.ts_…...

Claude3.5-Sonnet和GPT-4o怎么选(附使用链接)
随着人工智能模型的不断进化,传统的评估标准已经逐渐变得陈旧和不再适用。以经典的“喝水测试”为例,过去广泛应用于检测模型能力,但现如今即便是国内的一些先进模型,也能够轻松答对这些简单的问题。因此,我们亟需引入…...

使用itextpdf进行pdf模版填充中文文本时部分字不显示问题
在网上找了很多种办法 都解决不了; 最后发现是文本域字体设置出了问题; 在这不展示其他的代码 只展示重要代码; 1 引入扩展包 <dependency><groupId>com.itextpdf</groupId><artifactId>itext-asian</artifactId><version>5.2.0</v…...

java-贪心算法
1. 霍夫曼编码(Huffman Coding) 描述: 霍夫曼编码是一种使用变长编码表对数据进行编码的算法,由David A. Huffman在1952年发明。它是一种贪心算法,用于数据压缩。霍夫曼编码通过构建一个二叉树(霍夫曼树&a…...

OpenCV和Qt坐标系不一致问题
“ OpenCV和QT坐标系导致绘图精度下降问题。” OpenCV和Qt常用的坐标系都是笛卡尔坐标系,但是细微处有些不同。 01 — OpenCV坐标系 OpenCV是图像处理库,是以图像像素为一个坐标位置,即一个像素对应一个坐标,所以其坐标系也叫图像…...
前端VUE项目启动方式
将VUE项目的前端项目运行起来,整个过程非常简单,预计5分钟就可以完成,取决于大家的网速。 项目运行先安装Node.js Windows 安装 Node.js 指南:http://www.iocoder.cn/NodeJS/windows-install(opens new window) Mac 安装 Node.js…...
Python小白学习教程从入门到入坑------习题课5(基础巩固)
目录 实战题 1、“千年虫”是什么虫? 2、模拟京东购物流程 3、模拟12306火车票订票流程 4、模拟手机通讯录 实战题 1、“千年虫”是什么虫? 要求:已知一个列表中存储的是员工的出生年份 [88,89,90,98,00,99] 由于时间比较久,出生的年份均为2位整数…...
Python爬虫实战:研究MechanicalSoup库相关技术
一、MechanicalSoup 库概述 1.1 库简介 MechanicalSoup 是一个 Python 库,专为自动化交互网站而设计。它结合了 requests 的 HTTP 请求能力和 BeautifulSoup 的 HTML 解析能力,提供了直观的 API,让我们可以像人类用户一样浏览网页、填写表单和提交请求。 1.2 主要功能特点…...

手游刚开服就被攻击怎么办?如何防御DDoS?
开服初期是手游最脆弱的阶段,极易成为DDoS攻击的目标。一旦遭遇攻击,可能导致服务器瘫痪、玩家流失,甚至造成巨大经济损失。本文为开发者提供一套简洁有效的应急与防御方案,帮助快速应对并构建长期防护体系。 一、遭遇攻击的紧急应…...

【kafka】Golang实现分布式Masscan任务调度系统
要求: 输出两个程序,一个命令行程序(命令行参数用flag)和一个服务端程序。 命令行程序支持通过命令行参数配置下发IP或IP段、端口、扫描带宽,然后将消息推送到kafka里面。 服务端程序: 从kafka消费者接收…...
【Linux】C语言执行shell指令
在C语言中执行Shell指令 在C语言中,有几种方法可以执行Shell指令: 1. 使用system()函数 这是最简单的方法,包含在stdlib.h头文件中: #include <stdlib.h>int main() {system("ls -l"); // 执行ls -l命令retu…...

智能仓储的未来:自动化、AI与数据分析如何重塑物流中心
当仓库学会“思考”,物流的终极形态正在诞生 想象这样的场景: 凌晨3点,某物流中心灯火通明却空无一人。AGV机器人集群根据实时订单动态规划路径;AI视觉系统在0.1秒内扫描包裹信息;数字孪生平台正模拟次日峰值流量压力…...
DeepSeek 技术赋能无人农场协同作业:用 AI 重构农田管理 “神经网”
目录 一、引言二、DeepSeek 技术大揭秘2.1 核心架构解析2.2 关键技术剖析 三、智能农业无人农场协同作业现状3.1 发展现状概述3.2 协同作业模式介绍 四、DeepSeek 的 “农场奇妙游”4.1 数据处理与分析4.2 作物生长监测与预测4.3 病虫害防治4.4 农机协同作业调度 五、实际案例大…...
python报错No module named ‘tensorflow.keras‘
是由于不同版本的tensorflow下的keras所在的路径不同,结合所安装的tensorflow的目录结构修改from语句即可。 原语句: from tensorflow.keras.layers import Conv1D, MaxPooling1D, LSTM, Dense 修改后: from tensorflow.python.keras.lay…...

RabbitMQ入门4.1.0版本(基于java、SpringBoot操作)
RabbitMQ 一、RabbitMQ概述 RabbitMQ RabbitMQ最初由LShift和CohesiveFT于2007年开发,后来由Pivotal Software Inc.(现为VMware子公司)接管。RabbitMQ 是一个开源的消息代理和队列服务器,用 Erlang 语言编写。广泛应用于各种分布…...

《Docker》架构
文章目录 架构模式单机架构应用数据分离架构应用服务器集群架构读写分离/主从分离架构冷热分离架构垂直分库架构微服务架构容器编排架构什么是容器,docker,镜像,k8s 架构模式 单机架构 单机架构其实就是应用服务器和单机服务器都部署在同一…...

Visual Studio Code 扩展
Visual Studio Code 扩展 change-case 大小写转换EmmyLua for VSCode 调试插件Bookmarks 书签 change-case 大小写转换 https://marketplace.visualstudio.com/items?itemNamewmaurer.change-case 选中单词后,命令 changeCase.commands 可预览转换效果 EmmyLua…...