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

c++:类和对象中:拷贝构造和赋值运算符重载详解

c++:类和对象

构造函数和析构函数详解

`

文章目录

  • c++:类和对象
    • 构造函数和析构函数详解
  • 前言
  • 一、拷贝构造
    • 怎么写拷贝构造
      • 1.拷贝构造也是构造函数的一种,构造函数没有值.所以拷贝构造也没有返回值**
      • 2.拷贝构造只有一个形参,正常这个形参是自定义类型对象的引用.
      • 3. 如果我们没有显示写拷贝构造,编译器会自己生成.但是这种只是浅拷贝,在某些情况下面有危险
  • 二、赋值运算符重载
    • 代码实现
  • 总结


前言

拷贝构造,顾名思义就是复制.我们把一个已经创建自定义对象初始化创建新对象.
赋值运算符重载是把一个对象赋值给另一个对象,二者都是已创建的.


一、拷贝构造

怎么写拷贝构造

#include<iostream>
using namespace std;
class Date
{
public://构造函数,对自定义对象进行初始化Date(int year = 2004, int month = 4, int day = 30){_year = year;_month = month;_day = day;}//拷贝构造Date(const Date& d){_year = d._year;_month = d._month;_day = d._day;}friend ostream& operator<<(ostream & out, Date & d);
private:int _year;int _month;int _day;
};
//这个是<<的运算符重载
ostream& operator<<(ostream& out, Date& d)
{cout << d._year << "年" << d._month << "月" << d._day << "日" << endl;return out;
}int main()
{Date d1(2024,3,13);Date d2 = d1;cout << "d1:" << d1;cout << "d2:" << d2;return 0;
}

在这里插入图片描述

1.拷贝构造也是构造函数的一种,构造函数没有值.所以拷贝构造也没有返回值**

2.拷贝构造只有一个形参,正常这个形参是自定义类型对象的引用.

比如在Date这个类里面就是Date&.
为什么一定要是引用呢?我们都知道,函数的参数是一个形参,我们调用函数传过去的才是实参.而形参是实参的一个拷贝,我们要传值过去就必须创建一个形参.
我们传自定义类型Date的值时,因为要拷贝一个新对象,所以就要调用Date类型的拷贝构造.要是拷贝构造里面的参数也是Date的话,就会继续调用它的拷贝构造.如此形成无限递归.
在这里插入图片描述
传值调用拷贝构造编译器会自动报错

3. 如果我们没有显示写拷贝构造,编译器会自己生成.但是这种只是浅拷贝,在某些情况下面有危险

在这里插入图片描述

在这里插入图片描述

编译器默认的拷贝构造函数是按字节进行拷贝,在我们上面的日期类适用.因为我们没有动态开辟空间.

typedef int DataType;
class Stack
{
public:Stack(size_t capacity = 10){//动态开辟空间_array = (DataType*)malloc(capacity * sizeof(DataType));if (nullptr == _array){perror("malloc fail");return;}_size = 0;_capacity = capacity;}void Push(const DataType& data){_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;
}

上面的代码在程序运行会崩溃

这是为什么?编译器不是会按字节去对内置类型进行拷贝吗?
在这里插入图片描述
结果调试,发现问题出现在free上,free被调用了两次.同一块空间被删除了两次.这才是导致问题出现的关键
第一次free
在这里插入图片描述

第二次free
在这里插入图片描述
编译器默认写的是浅拷贝,也叫值拷贝.它只会按字节去拷贝.在我们动态开辟空间时,浅拷贝不会开辟空间.这样子会导致两个对象的_array指针指向同一块空间.
自定义类型结束后会调用它的析构函数.因为有两个对象,所以析构两次,free两次.

	Stack(Stack& st){DataType* tmp = (DataType*)malloc(st._capacity * sizeof(DataType));if (nullptr == tmp){perror("malloc申请空间失败");return;}memcpy(tmp, st._array, st._capacity* sizeof(DataType));_array = tmp;_size = st._size;_capacity = st._capacity;}

上面的类里面加上拷贝构造函数就不会报错,能够正常运行.这个也就是深拷贝.

二、赋值运算符重载


代码实现

`#include<iostream>
using namespace std;class Date
{
private:int _year;int _month;int _day;
public://构造函数,对自定义对象进行初始化Date(int year = 2004, int month = 4, int day = 30){_year = year;_month = month;_day = day;}//友元的声明friend ostream& operator<<(ostream& out, Date& d);//拷贝构造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;}
};运算符重载
ostream& operator<<(ostream& out, Date& d)
{cout << d._year << "年" << d._month << "月" << d._day << "日" << endl;return out;
}int main()
{Date d1(2024,3,28);Date d2;cout << "d1:" << d1;cout << "d2:" << d2;d2 = d1;cout << "d1:" << d1;cout << "d2:" << d2;return 0;
}`

赋值运算符重载和拷贝构造类似,本质还是对对象的拷贝.只不过拷贝构造是在对象初始化时运用的,赋值运算符是对已经存在的对象赋值
赋值运算符重载编译器默认生成的跟拷贝构造一样,都是浅拷贝
在这里插入图片描述
书写格式

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

1.operator是对内置操作符进行重载,如operator+
2.重载操作符必须有一个类型参数,最好用const修饰一下 , const Date&
3.形参总是比操作数少一(a=b有两个操作数),因为成员函数的第一个参数为this指针
4…
:: sizeof ?: . 注意以上5个运算符不能重载.面试/笔试可能会考
*

为什么返回值是Date&呢?
大家可能对这个问题比较好奇.
首先,我们的语言支持连等,我们可以同时给a,b,c三个变量赋值.

int main()
{int a,b,c;a = b = c = 10;return 0;
}

当我们把上面赋值运算符重载的代码改成无返回值时,我们的连续赋值就会报错.
在底层实现d3=d2=d1时,会调用赋值运算符重载这个函数,因为赋值是从右往左过去,故将d1赋值给d2,如果没有返回值的话,就没有人来给d3赋值.程序就会崩溃.所以返回值必须是左操作数的引用.

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

在这里插入图片描述

总结

拷贝构造和赋值运算符是同一类成员函数.不主动写编译器会默认生成.但是生成的这个只是浅拷贝,在日期类这种没有分配资源的类可以用
但是在有开辟空间的类上不适用,要自己写.

相关文章:

c++:类和对象中:拷贝构造和赋值运算符重载详解

c:类和对象 构造函数和析构函数详解 文章目录 c:类和对象构造函数和析构函数详解 前言一、拷贝构造怎么写拷贝构造1.拷贝构造也是构造函数的一种,构造函数没有值.所以拷贝构造也没有返回值**2.拷贝构造只有一个形参,正常这个形参是自定义类型对象的引用.3. 如果我们没有显示写…...

Day33:安全开发-JavaEE应用SQL预编译Filter过滤器Listener监听器访问控制

目录 JavaEE-预编译-SQL JavaEE-过滤器-Filter JavaEE-监听器-Listen 思维导图 Java知识点 功能&#xff1a;数据库操作&#xff0c;文件操作&#xff0c;序列化数据&#xff0c;身份验证&#xff0c;框架开发&#xff0c;第三方库使用等. 框架库&#xff1a;MyBatis&#…...

Log4j如何支持多线程环境?你如何优化Log4j的性能?

Log4j如何支持多线程环境&#xff1f; Log4j 通过其内部设计来支持多线程环境&#xff0c;确保在多线程应用程序中能够安全地使用。以下是 Log4j 支持多线程环境的一些关键方面&#xff1a; 线程安全性&#xff1a; Log4j 的 Logger 类和 Appender 类都是设计为线程安全的。这…...

golang sync.Pool 指针数据覆盖问题

场景 1. sync.Pool设置 var stringPool sync.Pool{New: func() any {return new([]string)}, }func NewString() *[]string {v : stringPool.Get().(*[]string)return v }func PutString(s *[]string) {if s nil {return}if cap(*s) > 2048 {s nil} else {*s (*s)[:0]…...

VUE+内置iframe传值失效问题解决

起因&#xff1a; 公司业务需要计算建筑物截收面积&#xff0c;然后我采用的是openCV来计算&#xff0c;在vue内部引用不了&#xff0c;然后就采用了iframe原生html来完成&#xff1b;功能实现了我想让iframe和vue通信&#xff1b;然后用原有方式试了多次都失败了&#xff0c;i…...

Day31:安全开发-JS应用WebPack打包器第三方库JQuery安装使用安全检测

目录 打包器-WebPack-使用&安全 第三方库-JQuery-使用&安全 思维导图 JS知识点&#xff1a; 功能&#xff1a;登录验证&#xff0c;文件操作&#xff0c;SQL操作&#xff0c;云应用接入&#xff0c;框架开发&#xff0c;打包器使用等 技术&#xff1a;原生开发&…...

Go Zero微服务个人探究之路(十六)回顾api服务和rpc服务的本质

目录 前言 正文 API&#xff08;Application Programming Interface&#xff09; RPC&#xff08;Remote Procedure Call&#xff09; API 与 RPC 的关系 分布式部署 API 和 RPC 结语 前言 go-zero 是一个基于 Go 语言的微服务框架&#xff0c;它提供了一套简洁的编程模…...

基于YOLOv8/YOLOv7/YOLOv6/YOLOv5的夜间车辆检测系统(深度学习代码+UI界面+训练数据集)

摘要&#xff1a;开发夜间车辆检测系统对于自动驾驶技术具有关键作用。本篇博客详细介绍了如何运用深度学习构建一个夜间车辆检测系统&#xff0c;并提供了完整的实现代码。该系统基于强大的YOLOv8算法&#xff0c;并对比了YOLOv7、YOLOv6、YOLOv5&#xff0c;展示了不同模型间…...

Spring体系架构

目录 核心容器(Core Container) 数据访问/集成(Data Access/Integration) Web开发(Web)...

【PLC】现场总线和工业以太网汇总

1、 现场总线 1.1 什么是现场总线 1&#xff09;非专业描述&#xff1a; 如下图&#xff1a;“人机界面”一般通过以太网连接“控制器(PLC)”&#xff0c;“控制器(PLC)”通过 “现场总线”和现场设备连接。 2&#xff09;专业描述&#xff08;维基百科&#xff09; 现场总线…...

【吊打面试官系列】Java虚拟机JVM篇 - 关于JVM分析

大家好&#xff0c;我是锋哥。今天分享关于JVM分析的JVM面试题&#xff0c;希望对大家有帮助&#xff1b; 查看JVM进程号的命令是什么? 可以使用 ps ‐ef 和 jps ‐v 等等。 怎么查看剩余内存? 比如&#xff1a; free ‐m, free ‐h, top 命令等等。 1000道 互联网大厂Jav…...

Mysql锁与MVCC

文章目录 Mysql锁的类型锁使用MVCC快照读和当前读读视图【Read View】串行化的解决 exlpain字段解析ACID的原理日志引擎整合SpringBoot博客记录 Mysql锁的类型 MySQL中有哪些锁&#xff1a; 乐观锁&#xff08;Optimistic Locking&#xff09;&#xff1a;假设并发操作时不会发…...

rancher是什么

Rancher Labs是制作Rancher的公司。Rancher Labs成立于2014年&#xff0c;是一家专注于企业级容器管理软件的公司。它的产品设计旨在简化在分布式环境中部署和管理容器的过程&#xff0c;帮助企业轻松地采用容器技术和Kubernetes。Rancher Labs提供的Rancher平台支持Docker容器…...

阿里云服务器安全狗免费使用多引擎智能查杀引擎

云服务器具有按量付费、降低综合成本等诸多优势&#xff0c;受到很多企业的欢迎。 因此&#xff0c;目前使用的云服务器越来越多。 阿里云是目前云服务器中最具影响力的品牌&#xff0c;因此选择阿里云服务器的用户数量也是最多的。 那么阿里云服务器需要安装杀毒软件吗&#x…...

使用rust实现九九乘法表

rust目前拥有接近c/c的运行速度以及更快的编码支持&#xff0c;所以是很值得学习得一门语言。rust的语法及设计理念与其他的语言也有许多的不同之处。比如其特有的所有权属性。可以让开发者快速的开发出高效的运行程序。对于内存的管理也有极好的管理方案。 在这里使用rust语言…...

突破编程_C++_设计模式(简单工厂模式)

1 简单工厂模式的概念 简单工厂模式&#xff08;Simple Factory Pattern&#xff09;是设计模式中的一种创建型模式。它的主要目的是将对象的实例化与使用解耦&#xff0c;使得客户端无需关心对象的创建细节&#xff0c;只需通过工厂类来获取所需的对象。 在简单工厂模式中&a…...

C语言——快速排序

C语言——快速排序 一、 含义二、算法思想三、实现步骤代码实现 一、 含义 快速排序算法是在几种排序算法中效率最高的一个排序算法了&#xff0c;故称为快速排序&#xff0c;它的时间复杂度为&#xff1a;O(nlog2n)&#xff0c;相比冒泡排序算法的O(n2)有很大的提升。 二、算…...

FP独立站获客秘籍大揭秘:简单高效,一看就会!

跨境电商的大潮中&#xff0c;越来越多的卖家选择跳出第三方平台的框架&#xff0c;拥抱独立站的自由与机遇。但独立站获客难、成本高的问题&#xff0c;也让不少卖家头疼不已。别担心&#xff0c;今天就来给大家揭秘FP独立站获客的简单高效方法&#xff01; 首先&#xff0c;…...

英伟达tx2光驱烧录功能支持

今天得到一个任务&#xff0c;是在当前nvidia tx2平台上使能usb cdrom并且调试烧录功能。首先测试给到的信息是不能在平台上使用&#xff08;废话嘛&#xff0c;能用还用我干嘛&#xff09; 拿到本地ubuntu机器上看了下&#xff0c;使用brasero等软件可以顺利烧录。 此时捕获了…...

关于stm32(CubeMX+HAL库)的掉电检测以及flash读写

1.掉电检测 CubeMX配置 只需使能PVD中断即可 但是使能了PVD中断后还需要自行配置一些PWR寄存器中的参数&#xff0c;我也通过HAL库进行编写 void PVD_config(void) {//配置PWRPWR_PVDTypeDef sConfigPVD; sConfigPVD.PVDLevel PWR_PVDLEVEL_7; …...

XML Group端口详解

在XML数据映射过程中&#xff0c;经常需要对数据进行分组聚合操作。例如&#xff0c;当处理包含多个物料明细的XML文件时&#xff0c;可能需要将相同物料号的明细归为一组&#xff0c;或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码&#xff0c;增加了开…...

超短脉冲激光自聚焦效应

前言与目录 强激光引起自聚焦效应机理 超短脉冲激光在脆性材料内部加工时引起的自聚焦效应&#xff0c;这是一种非线性光学现象&#xff0c;主要涉及光学克尔效应和材料的非线性光学特性。 自聚焦效应可以产生局部的强光场&#xff0c;对材料产生非线性响应&#xff0c;可能…...

label-studio的使用教程(导入本地路径)

文章目录 1. 准备环境2. 脚本启动2.1 Windows2.2 Linux 3. 安装label-studio机器学习后端3.1 pip安装(推荐)3.2 GitHub仓库安装 4. 后端配置4.1 yolo环境4.2 引入后端模型4.3 修改脚本4.4 启动后端 5. 标注工程5.1 创建工程5.2 配置图片路径5.3 配置工程类型标签5.4 配置模型5.…...

【HTML-16】深入理解HTML中的块元素与行内元素

HTML元素根据其显示特性可以分为两大类&#xff1a;块元素(Block-level Elements)和行内元素(Inline Elements)。理解这两者的区别对于构建良好的网页布局至关重要。本文将全面解析这两种元素的特性、区别以及实际应用场景。 1. 块元素(Block-level Elements) 1.1 基本特性 …...

OpenLayers 分屏对比(地图联动)

注&#xff1a;当前使用的是 ol 5.3.0 版本&#xff0c;天地图使用的key请到天地图官网申请&#xff0c;并替换为自己的key 地图分屏对比在WebGIS开发中是很常见的功能&#xff0c;和卷帘图层不一样的是&#xff0c;分屏对比是在各个地图中添加相同或者不同的图层进行对比查看。…...

基于matlab策略迭代和值迭代法的动态规划

经典的基于策略迭代和值迭代法的动态规划matlab代码&#xff0c;实现机器人的最优运输 Dynamic-Programming-master/Environment.pdf , 104724 Dynamic-Programming-master/README.md , 506 Dynamic-Programming-master/generalizedPolicyIteration.m , 1970 Dynamic-Programm…...

CVE-2020-17519源码分析与漏洞复现(Flink 任意文件读取)

漏洞概览 漏洞名称&#xff1a;Apache Flink REST API 任意文件读取漏洞CVE编号&#xff1a;CVE-2020-17519CVSS评分&#xff1a;7.5影响版本&#xff1a;Apache Flink 1.11.0、1.11.1、1.11.2修复版本&#xff1a;≥ 1.11.3 或 ≥ 1.12.0漏洞类型&#xff1a;路径遍历&#x…...

PAN/FPN

import torch import torch.nn as nn import torch.nn.functional as F import mathclass LowResQueryHighResKVAttention(nn.Module):"""方案 1: 低分辨率特征 (Query) 查询高分辨率特征 (Key, Value).输出分辨率与低分辨率输入相同。"""def __…...

LangChain知识库管理后端接口:数据库操作详解—— 构建本地知识库系统的基础《二》

这段 Python 代码是一个完整的 知识库数据库操作模块&#xff0c;用于对本地知识库系统中的知识库进行增删改查&#xff08;CRUD&#xff09;操作。它基于 SQLAlchemy ORM 框架 和一个自定义的装饰器 with_session 实现数据库会话管理。 &#x1f4d8; 一、整体功能概述 该模块…...

免费数学几何作图web平台

光锐软件免费数学工具&#xff0c;maths,数学制图&#xff0c;数学作图&#xff0c;几何作图&#xff0c;几何&#xff0c;AR开发,AR教育,增强现实,软件公司,XR,MR,VR,虚拟仿真,虚拟现实,混合现实,教育科技产品,职业模拟培训,高保真VR场景,结构互动课件,元宇宙http://xaglare.c…...