C++万物起源:类与对象(三)拷贝构造、赋值重载

目录

一、拷贝构造函数

1.1拷贝构造函数的概念与特征

1.2拷贝构造的实现

1.3默认构造函数

1.4拷贝构造函数典型调用场景

二、赋值运算符重载

2.1赋值运算符重载的格式


一、拷贝构造函数

1.1拷贝构造函数的概念与特征

在c语言语法中,我们可以将一个变量赋值给和它统一类型的变量,而在C++中,同样可以使用拷贝构造函数实现。

拷贝构造函数:只有单个形参,该形参是对本类类型对象的引用(一般常用const修饰),在用已存 在的类类型对象创建新对象时由编译器自动调用。

拷贝构造函数也是特殊的成员函数,其特征如下:

1. 拷贝构造函数是构造函数的一个重载形式。

2. 拷贝构造函数的参数只有一个且必须是类类型对象的引用,使用传值方式编译器直接报错, 因为会引发无穷递归调用。

1.2拷贝构造的实现

class Date
{
public:
    Date(int year = 1900, int month = 1, int day = 1)
    {
        _year = year;
        _month = month;
        _day = day;
    }
    // Date(const Date& d)   // 正确写法
    Date(const Date& d)   // 错误写法:编译报错,会引发无穷递归
    {
        _year = d._year;
        _month = d._month;
        _day = d._day;
    }
private:
    int _year;
    int _month;
    int _day;
};
int main()
{
    Date d1;
    Date d2(d1);
    return 0;
}

注意:拷贝构造的参数必须用引用来接受,因为用户传过来的是一个对象,如果直接拿一个该类型的对象作为函数参数来进行接收,这个参数在接收被拷贝的对象时 就会去调用拷贝构造然后再将值传下去,这样就会引发无穷递归调用。

1.3默认构造函数

若未显式定义,编译器会生成默认的拷贝构造函数。 默认的拷贝构造函数对象按内存存储按
字节序完成拷贝,这种拷贝叫做浅拷贝,或者值拷贝。
class Time
{
public:
	Time()
	{
		_hour = 1;
		_minute = 1;
		_second = 1;
	}
	Time(const Time& t)
	{
		_hour = t._hour;
		_minute = t._minute;
		_second = t._second;
		cout << "Time::Time(const Time&)" << endl;
	}
private:
	int _hour;
	int _minute;
	int _second;
};
class Date
{
private:
	// 基本类型(内置类型)
	int _year = 1970;
	int _month = 1;
	int _day = 1;
	// 自定义类型
	Time _t;
};
int main()
{
	Date d1;

	// 用已经存在的d1拷贝构造d2,此处会调用Date类的拷贝构造函数
	// 但Date类并没有显式定义拷贝构造函数,则编译器会给Date类生成一个默认的拷贝构
	造函数
		Date d2(d1);
	return 0;
}
在编译器生成的默认拷贝构造函数中,内置类型是按照字节方式直接拷贝的,而自定
义类型是调用其拷贝构造函数完成拷贝的。
编译器生成的默认拷贝构造函数已经可以完成字节序的值拷贝了,还需要自己显式实现吗?
当然像日期类这样的类是没必要的。那么下面的类呢?验证一下试试?
typedef int DataType;
class Stack
{
public:
	Stack(size_t capacity = 10)
	{
		_array = (DataType*)malloc(capacity * sizeof(DataType));
		if (nullptr == _array)
		{
			perror("malloc申请空间失败");
			return;
		}
		_size = 0;
		_capacity = capacity;
	}
	void Push(const DataType& data)
	{
		// CheckCapacity();
		_array[_size] = data;
		_size++;
	}
	~Stack()
	{
		if (_array)
		{
			free(_array);
			_array = nullptr;
			_capacity = 0;
			_size = 0;
		}
	}
private:
	DataType* _array;
	size_t _size;
	size_t _capacity;
};
int main()
{
	Stack s1;
	s1.Push(1);
	s1.Push(2);
	s1.Push(3);
	s1.Push(4);
	Stack s2(s1);
	return 0;
}

注意:类中如果没有涉及资源申请时,拷贝构造函数是否写都可以;一旦涉及到资源申请
时,则拷贝构造函数是一定要写的,否则就是浅拷贝。

 

1.4拷贝构造函数典型调用场景

1.使用已存在对象创建新对象
2.函数参数类型为类类型对象
3.函数返回值类型为类类型对象
为了提高程序效率,一般对象传参时,尽量使用引用类型,返回时根据实际场景,能用引用
尽量使用引用。

二、赋值运算符重载

C++为了增强代码的可读性引入了运算符重载运算符重载是具有特殊函数名的函数,也具有其
返回值类型,函数名字以及参数列表,其返回值类型与参数列表与普通的函数类似。
函数名字为:关键字operator后面接需要重载的运算符符号
函数原型:返回值类型 operator操作符(参数列表)。
  注意:
不能通过连接其他符号来创建新的操作符:比如operator@
重载操作符必须有一个类类型参数
用于内置类型的运算符,其含义不能改变,例如:内置的整型+,不 能改变其含义
作为类成员函数重载时,其形参看起来比操作数数目少1,因为成员函数的第一个参数为隐
藏的this
1.*  2::  3sizeof 4? 5: . 注意以上5个运算符不能重载。这个经常在笔试选择题中出现。  

2.1赋值运算符重载的格式

参数类型:const T&,传递引用可以提高传参效率
返回值类型:T&,返回引用可以提高返回的效率,有返回值目的是为了支持连续赋值
检测是否自己给自己赋值
返回*this :要复合连续赋值的含义
class Date
{
public:
	Date(int year = 1900, int month = 1, int day = 1)
	{
		_year = year;
		_month = month;
		_day = day;
	}

	// bool operator==(Date* this, const Date& d2)
	// 这里需要注意的是,左操作数是this,指向调用函数的对象
	bool operator==(const Date & d2)
	{
		return _year == d2._year;
		&& _month == d2._month
			&& _day == d2._day;
	}
private:
	int _year;
	int _month;
	int _day;
};
class Date
{
public:
	Date(int year = 1900, int month = 1, int day = 1)
	{
		_year = year;
		_month = month;
		_day = day;
	}

	Date(const Date& d)
	{
		_year = d._year;
		_month = d._month;
		_day = d._day;
	}

	Date& operator=(const Date& d)
	{
		if (this != &d)
		{
			_year = d._year;
			_month = d._month;
			_day = d._day;
		}

		return *this;
	}
private:
	int _year;
	int _month;
	int _day;
};
赋值运算符只能重载成类的成员函数不能重载成全局函数
class Date
{
public:
	Date(int year = 1900, int month = 1, int day = 1)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	int _year;
	int _month;
	int _day;
};
// 赋值运算符重载成全局函数,注意重载成全局函数时没有this指针了,需要给两个参数
Date& operator=(Date& left, const Date& right)
{
	if (&left != &right)
	{
		left._year = right._year;
		left._month = right._month;
		left._day = right._day;
	}
	return left;
}
// 编译失败:
// error C2801: “operator =”必须是非静态成员
原因:赋值运算符如果不显式实现,编译器会生成一个默认的。此时用户再在类外自己实现
一个全局的赋值运算符重载,就和编译器在类中生成的默认赋值运算符重载冲突了,故赋值
运算符重载只能是类的成员函数。
用户没有显式实现时,编译器会生成一个默认赋值运算符重载,以值的方式逐字节拷贝。注
意:内置类型成员变量是直接赋值的,而自定义类型成员变量需要调用对应类的赋值运算符
重载完成赋值。
既然编译器生成的默认赋值运算符重载函数已经可以完成字节序的值拷贝了,还需要自己实
现吗?当然需要 如果类中未涉及到资源管理,赋值运算符是否实现都可以;一旦涉及到资源管理则必须要实现。
比如之前的stack,如果不重载赋值,就会导致两个对象指向同一块空间,从而最后调用两次析构导致程序崩溃。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

2024 ccfcsp认证打卡 2023 05 01 重复局面

2023 05 01 重复局面 题目题解1题解2区别&#xff1a;数据存储方式&#xff1a;时间复杂度&#xff1a;空间复杂度&#xff1a; 总结&#xff1a; 题目 题解1 import java.util.*;public class Main {public static void main(String[] args) {Scanner input new Scanner(Sys…

自动驾驶传感器:传感的本质

自动驾驶传感器&#xff1a;传感的本质 附赠自动驾驶学习资料和量产经验&#xff1a;链接 0. 前言 这个系列的背景是&#xff1a;工作时候需要攒一台数据采集车辆&#xff0c;那段时间需要熟悉感知硬件&#xff0c;写了不少笔记&#xff0c;都是些冗长的文章&#xff0c;感兴…

【pysurvival Python 安装失败】

这个错误与 sklearn 包的名称更改有关&#xff0c;导致 pysurvival 在构建元数据时失败。现在&#xff0c;你需要修改 pysurvival 的安装文件以使用正确的 scikit-learn 包名 编辑安装文件&#xff1a;找到 pysurvival 的安装文件&#xff0c;可能是 setup.py 或 pyproject.to…

OpenAI 15秒重建逼真人声,百度早就实现啦!只需2秒生成完美音色,免费使用

大家好&#xff0c;我是卖萌酱。 这两天&#xff0c;卖萌酱发现有不少读者小伙伴都在关注几天前我们介绍的OpenAI刚刚发布的这个名为Voice Engine 的语音引擎。这个听起来颇为“Amazing”的“黑科技”&#xff0c;可以仅仅凭借一段15秒的声音样本&#xff0c;就能精准模仿这段…

pytest--python的一种测试框架--接口测试

接口测试 工具&#xff1a; POSTMAN&#xff1b; 接口选择&#xff1a; 豆瓣电影&#xff0c;进制数据 POSTMAN下载&#xff1a; 1.POSTMAN官网&#xff1a;https://www.postman.com/products/&#xff1b; 2.点product选Download Postman 下载完之后双击打开就可以用的。…

【智能算法】金枪鱼群优化算法(TSO)原理及实现

目录 1.背景2.算法原理2.1算法思想2.2算法过程 3.代码展示4.参考文献 1.背景 2021年&#xff0c;Xie等人受到自然界中金枪鱼狩猎行为启发&#xff0c;提出了金枪鱼优化算法&#xff08;Tuna swarm optimization&#xff0c;TSO&#xff09;。 2.算法原理 2.1算法思想 TSO模…

黑马鸿蒙笔记

目录 25-Stage模型-页面及组件生命周期 26-Stage模型-UIAbility的启动模式 25-Stage模型-页面及组件生命周期 26-Stage模型-UIAbility的启动模式 singleton 只会有一个实例 multiton 会有多个&#xff0c;但是会销毁旧的 standard 会有多个&#xff0c;但是不会销毁

深入了解与全面解析华为认证(HCIA/HCIP/HCIE)

一、网络行业技术认证 网络行业对于技术评定一般分为两种&#xff0c;一种是企业认证&#xff0c;一种是国家认证 企业认证属于技术认证&#xff0c;在国内的互联网企业都会承认&#xff0c;用于评定一个人的技术等级或者企业招投标的资质。 网络行业认证最好的有三种&#…

开源知识管理和协作平台:插件丰富,主题精美 | 开源日报 No.209

logseq/logseq Stars: 27.8k License: AGPL-3.0 logseq 是一个注重隐私的开源平台&#xff0c;用于知识管理和协作。 提供强大的知识管理、协作、PDF 标注和任务管理工具支持多种文件格式&#xff0c;包括 Markdown 和 Org-modeWhiteboard 功能可使用空间画布组织想法&#x…

【THM】Nmap Live Host Discovery(Nmap 实时主机发现)-初级渗透测试

介绍 当我们想要针对一个网络时,我们希望找到一个高效的工具来帮助我们处理重复性任务并回答以下问题: 哪些系统已启动?这些系统上正在运行哪些服务?我们将依赖的工具是Nmap。关于寻找在线计算机的第一个问题将在这个房间得到解答。该房间是专门讨论Nmap的四个房间系列中的…

.pth文件转化为onnx文件,并进行可视化

1、文件转化 import torch.onnx from torchvision import models from onnxsim import simplify import onnx torch_model torch.load("D:\checkpoint-epoch40.pth",map_locationcpu) # pytorch模型加载 model models.resnet50() # model.load_state_dict(torch_…

视频监控/云存储/磁盘阵列/AI智能分析平台EasyCVR集成时调用接口报跨域错误是什么原因?

EasyCVR视频融合平台基于云边端架构&#xff0c;可支持海量视频汇聚管理&#xff0c;能提供视频监控直播、云端录像、云存储、录像检索与回看、智能告警、平台级联、智能分析等视频服务。平台兼容性强&#xff0c;支持多协议、多类型设备接入&#xff0c;包括&#xff1a;国标G…

C++中的List容器用法详解

文章目录 C中的List容器用法详解List 的特点List 的重要接口用法介绍1.创建和初始化Listlist 2.插入元素push_backpush_forntinsert 删除元素pop_backpop_fontclearerase 遍历List迭代器遍历范围for遍历 排序Listsort 反转Listreverse 转移Listsplice 去重unique 合并merge 总结…

语言模型进化史(上)

由于篇幅原因&#xff0c;本文分为上下两篇&#xff0c;上篇主要讲解语言模型从朴素语言模型到基于神经网络的语言模型&#xff0c;下篇主要讲解现代大语言模型以及基于指令微调的LLM。文章来源是&#xff1a;https://www.numind.ai/blog/what-are-large-language-models 一、语…

【国信华源2024年首场春季校园招聘面试会举办】

阳春三月&#xff0c;春意盎然&#xff0c;北京国信华源科技有限公司2024年校园招聘活动如期展开。4月2日&#xff0c;成功举办了“国信华源2024年首场春季校园招聘面试会”。 国信华源公司人力资源部热情接待了前来参加面试的同学们&#xff0c;并亲自陪同他们深入探访了企业。…

《pytorch深度学习实战》学习笔记第1章

第1章 深度学习和pytorch库简介 1.1 深度学习革命 机器学习依赖特征工程。而深度学习是从原始数据中自动找出这样的特征。 1.2 pytorhc深度学习 pytorch是一个python程序库。pytorch为深度学习提供了入门指南。pytorch的核心数据结构——张量&#xff0c;为一个多维数组&…

人工智能上手 Pytorch

人工智能上手 Pytorch 1、人工智能框架历史走向 2015年&#xff0c; caffe&#xff0c;优势配置简单&#xff0c;缺点安装麻烦&#xff0c;且不更新维护 2016年&#xff0c;tensorflow 1.x&#xff0c;定义太严格&#xff0c;很复杂。开发成本高。简单的任务&#xff0c;也很…

Ardupilot无人船(车)各控制模式简介

本文介绍了Ardupilot固件无人船(车)的各种模式。 用户通常使用遥控器开关设置无人船(车)模式。也可以使用地面站更改模式。 对于3档开关&#xff0c;通常最好将一个开关位置设置为HOLD&#xff0c;另一个设置为MANUAL&#xff0c;第三个设置为STEERING或AUTO。 一、ACRO模式 …

C++中的string类模拟实现

目录 string类的模拟实现 string类的构造函数 string类拷贝构造函数 string类析构函数 string类c_str()函数 string类中的[]运算符重载函数 string类中的赋值运算符重载 string类中获取字符串有效字符个数 string类中获取字符串存储空间大小&#xff08;不包括\0&…

把标注数据导入到知识图谱

文章目录 简介数据导入Doccano标注数据&#xff0c;导入到Neo4j寻求帮助 简介 团队成员使用 Doccano 标注了一些数据&#xff0c;包括 命名实体识别、关系和文本分类 的标注的数据&#xff1b; 工作步骤如下&#xff1a; 首先将标注数据导入到Doccano&#xff0c;查看一下标注…