C++基础语法:复制构造函数,赋值构造函数及浅复制,深复制
前言
"打牢基础,万事不愁" .C++的基础语法的学习
引入
前一篇帖子C++基础语法:类构造函数之普通构造函数-CSDN博客讲了普通构造函数,还有 复制构造函数,赋值运算符以及延伸出来的浅复制和深复制问题,做个补充.
内容主要参考自<<C++ Prime Plus>> 6th Edition 第12章 类和动态内存分配
题外话
先说说个人心得,这部分内容是C++学习首次接触时,开始觉得杂乱的地方,也可以说是第一个难点(当然后面还有多种继承方式,多重继承啊,模板啊,算法啊,也不容易).所以需要好好梳理他的来龙去脉. 类可以包络一切数据和逻辑,类写完了,程序差不多就完成了.所以构造类对象比较重要.
再谈谈学习方法,纯记忆学习,很牢靠也很让人踏实.但有两个问题,一是记不记得了那么多,有的人记忆力没那么好.二是容易造成一个不爱思考的"舒适区",编程本身就是在表达逻辑,比使用逻辑要深一层.所以学习最好能建立逻辑链,以"现有知识"推导"未知",同时把"未知"变为"已知"
复制构造函数
对象的生成方法,不止使用普通构造函数,还可以使用复制构造函数.他们在形式上有差别.普通构造函数,使用了非对象做参数;复制构造函数,使用已生成的对象做参数,生成新的对象.例如:
#include<iostream>
using namespace std;
class Person { //类声明string description;double money;
public:Person(const string& des, double mo) :description(des), money(mo) {}double getMoney() {return money;}string getDescription() {return description;}
};int main(void) {Person Annie = Person("beautiful", 5000); //普通构造函数生成对象安妮Person Julie(Annie); //复制构造函数生成对象朱丽,属性值和安妮相同cout << "安妮的私房钱:" << Annie.getMoney() << endl;cout << "朱莉的私房钱:" << Julie.getMoney() << endl;
}
----对象Annie的生成调用了普通构造函数,对象Julie的生成调用了复制构造函数.
复制构造函数还有另外几种形式: 不用可以去记忆,他们的共同特征是以已有对象做参数.
Person Julie=Annie;
Person Julie=Person(Annie);
Person *pJulie=new Person(Annie);
赋值运算符
和复制构造函数几乎相同:
Person Rebecca; //声明对象瑞贝卡Rebecca = Julie; //将Julie的属性值赋给Rebeccacout << "瑞贝卡的私房钱:" << Rebecca.getMoney() << endl;
=============================================================Person(){} //类声明中加上默认构造函数,否则报错
函数原型及浅复制
每个类存在默认复制构造函数和默认赋值运算符,本例中的原型是:
Person (const Person&); //默认复制构造函数原型
Person& Person::operator=(const Person&); //赋值运算符重载
他表达的逻辑: 传入已有对象时,将对象的属性值赋给新对象,
===========================内容分割线:小思考=============================
疑问:原型内部逻辑怎样实现属性值复制?
java里有反射机制,可以获得每个类的属性和方法,C++没有明确说明是怎样实现"反射"的.但可以肯定的是:一定存在类似反射的机制,可以获得每个类的属性.他有可能被封装进源码里,没有将接口开放给程序员.
===========================内容分割线:小思考=============================
浅复制的问题
篇幅所限,代码参考<<C++ Prime Plus>> 6th Edition 第12章 类和动态内存分配 中的String类
1>无法处理类静态变量
这里必须说明,因为静态变量num_strings是表示生成对象的数量,在普通构造函数中有所表示---每生成一个对象,num_strings++;而在默认的复制构造函数和赋值符"="的定义中,没有表示,所以会造成调用后两种方法生成对象时,不会记录到静态变量中.----这不是语法造成的,而是逻辑上的错误.自定义默认构造函数和赋值符解决
2>当传入指针,并在析构函数中调用delete删除指针指向对象,又把对象浅复制,并且两次调用析构函数.
第2个问题的条件比较长,分两步来理解.
首先是类设计时,有指针传入; 在析构函数中调用delete删除指针指向的对象.
然后在生成对象object后,浅复制生成了新对象newObject(可能有多个).两次或多次调用析构函数释放内存,使删除出错. -----原因:C++两次释放同一块空间会出现错误.
浅复制问题的解决:深复制
深复制可以解决浅复制带来的问题,操作也比较简单,不管是普通构造函数,复制构造函数,赋值运算符重载,都用new开辟一块内存空间,复制传入指针指向的数据,在析构函数里定义delete.那么不管怎样复制对象,每生成一个对象,调用delete一次,不会出错.
深复制的问题
以下内容书上没有,属于自己总结,有版权:)
===========================内容分割线:小思考============================
为什么要给类传入指针?
C++是追求性能的语言,试想这种场景:尽可能的占用少的内存.内存分为三块:静态内存,局部变量使用内存,动态内存;那么可以推导出程序运行占用的内存只有类定义,函数定义(这些空间无法节省),所有的数据都用new动态生成,用完即删除.所以传入的指针都是new生成的.
===========================内容分割线:小思考============================
深复制有以下两个问题:
1>和以上内容存在悖论,为了正确的删除,占用了更多的内存空间.
2>给指针分配多少内存合适?书上的例子是char *指针,可以求出其占用空间,若指针指向数组,可以用sizeof()求出,如果指针指向链表或者其他数据集合又该怎么办呢?
深复制问题的解决
1>所有构造函数定义和赋值运算符重载都不用new分配空间(比书上还省一点),什么时候删除指针指向的数据,全由程序员自己掌握.举例:
class Demo { //演示类,属性有指针int* demo;
public:Demo(int * de):demo(de){}void show() {cout << "数组中的第1个数字是:" << *demo << endl;}
// ~Demo() { delete[] demo; }; //若启用则删除传入指针指向数据,和"delete[] a"互斥
};
================================================================
int main(void) {int *a=new int[] { 10,20 }; //动态分配空间建立数组,生成指针aDemo *d=new Demo(a); //传入指针,并动态生成对象dd->show();delete d; //删除动态生成对象dcout << "现在数组中第1个数字是" << *a << endl;delete[] a; //手动删除a,需要注释~Demo()否则报错
}
----说明:又回到浅复制了, 代码少了许多(如果解决静态变量问题需补上定义)
2>不要传入指针,把数据放到一个类里,传入该类对象的引用.用对象引用去控制数据,内存占一点也没关系,省事多了.需要新对象的话再用普通构造函数生成一个
----说明:不要说深复制,浅复制都被省了,整个12章的内容几乎都被省去了.对作者和书的内容无可厚非,设计了这种机制,也讲清楚了.
小结
C++构造函数的理解和应用
相关文章:
C++基础语法:复制构造函数,赋值构造函数及浅复制,深复制
前言 "打牢基础,万事不愁" .C的基础语法的学习 引入 前一篇帖子C基础语法:类构造函数之普通构造函数-CSDN博客讲了普通构造函数,还有 复制构造函数,赋值运算符以及延伸出来的浅复制和深复制问题,做个补充. 内容主要参考自<<C Prime Plus>> 6th Edition …...

架构是怎样练成的-楼宇监控系统案例
目录 概要 项目背景 原系统设计方案 改进后的设计方案 小结 概要 绝大多数人掌握的架构都是直接学习,慢慢地才能体会到一个架构的好处。架构是一种抽象,是为了复用目的而对代码做的抽象。通过一个项目的改造,理解架构是如何产生的&…...

valgrind使用浅谈
1、Valgrind 简介 Valgrind是一款用于内存调试、内存泄漏检测以及性能分析的软件开发工具,它可在以下平台上运行: X86/Linux、AMD64/Linux、ARM/Linux、ARM64/Linux、PPC32/Linux、PPC64/Linux、PPC64LE/Linu x、S390X/Linux、MIPS32/Linux、MIPS64/Li…...

强化学习专题:强化学习知识梳理(一)
2024/6/23: 前段时间有幸完成了大学期间的第一篇论文。在面试之前复盘一下关于自己论文中DQN的一些相关点。 浅谈主要区别(在线 or 离线) 首先,一切的开始是强化学习中时序差分方程,这体现了强化学习方法的优化策略。在…...

深入JVM:详解JIT即时编译器
文章目录 深入JVM:详解JIT即时编译器一、序言二、基础概念1、何为JIT即时编译2、热点代码 三、HotSpot内置的即时编译器1、C1编译器2、C2编译器3、分层编译3.1 协作流程 四、常见JIT优化技术1、方法内联2、逃逸分析(1)同步锁消除(…...

ORBSLAM3_ROS_Ubuntu18_04环境搭建安装
orbslam3安装 ORB-SLAM3配置及安装教程(2023.3)_orbslam3安装-CSDN博客 换源,换成国内的 搜索software 安装工具 sudo apt install git sudo apt update sudo apt install gcc g cmake安装 cmake安装新版本 ubuntu20.04安装cmake详细…...

【opencv - C++ - Ubuntu】putText 显示中文最快方法
话不多说,直接上代码 #include <iostream> #include <opencv2/opencv.hpp> #include <opencv2/freetype.hpp>using namespace std; using namespace cv;int main(void) {Mat image(1000, 1800, CV_8UC3, Scalar(200,162,33));Ptr<freetype::F…...

百度网盘下载速度慢的解决办法
目录 一、背景 二、解决办法 1、点击三个竖点,再点设置 2、点击传输,再点击去开启该功能 3、点击同意,开启优化速率 三、结果 四、备注 一、背景 当你不是百度网盘会员时,你在使用百度网盘下载时,是否下载速度太…...
Python api接口 异步
Python API接口异步编程简介 在现代的软件开发中,大多数应用都需要通过API接口与其他系统进行交互。Python是一种非常流行的编程语言,因此许多开发者选择使用Python来构建他们的API接口。在一些情况下,API接口需要进行异步编程,以…...
Java 和 Kotlin 单例模式写法对比
目录 1、饿汉模式 Java 写法: Kotlin 写法: Kotlin 这段代码反编译&简化后如下: 2、懒汉模式,静态同步方法 Java 写法: Kotlin 写法: Kotlin 这段代码反编译&简化后如下: 3、懒…...
解析connectionReset异常的原因与解决方案
解析connectionReset异常的原因与解决方案 大家好,我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编,也是冬天不穿秋裤,天冷也要风度的程序猿!今天我们将深入探讨Java中connectionReset异常的原因及其解决方案。这…...

mindspore打卡第9天 transformer的encoder和decoder部分
mindspore打卡第9天 transformer的encoder和decoder部分 import mindspore from mindspore import nn from mindspore import ops from mindspore import Tensor from mindspore import dtype as mstypeclass ScaledDotProductAttention(nn.Cell):def __init__(self, dropout_…...
Python实现IPv4地址和16进制互相转换
Python实现IPv4地址和16进制互相转换 import socketdef ip_to_hex16(ipaddr):# 使用 socket 库中的方法将IP地址转换为网络字节序的二进制表示hex_bytes socket.inet_aton(ipaddr)# 将二进制数据转换为整数, 其中byteorderbig 表示使用大端字节序(从高位到低位&…...

计算机视觉 | 基于图像处理和边缘检测算法的黄豆计数实验
目录 一、实验原理二、实验步骤1. 图像读取与预处理2. 边缘检测3. 轮廓检测4. 标记轮廓序号 三、实验结果四、完整代码 Hi,大家好,我是半亩花海。 本实验旨在利用 Python 和 OpenCV 库,通过图像处理和边缘检测算法实现黄豆图像的自动识别和计…...

深入分析 Android BroadcastReceiver (七)
文章目录 深入分析 Android BroadcastReceiver (七)1. 高级应用场景1.1 示例:动态权限请求1.2 示例:应用内通知更新 2. 安全性与性能优化2.1 示例:设置权限防止广播攻击2.2 示例:使用 LocalBroadcastManager2.3 示例:在…...

C++中的数据结构
一.STL标准库 结构:STL中有六大组件,分别是:容器,算法,迭代器,仿函数,配接器,配置器;以下分别介绍这六大组件中的最主要的三个。 1.容器 容器来配置存储空间,算法通过…...

武汉星起航:一站式服务,助力亚马逊卖家高效运营,实现收益飞跃
在跨境电商的浪潮中,武汉星起航电子商务有限公司以其独特的一站式跨境电商服务,为众多亚马逊卖家提供了强有力的支持,助力他们在不断发展的市场中脱颖而出,实现收益的大幅提升。 武汉星起航的一站式跨境电商服务,以其…...

从灵感到实践:Kimi辅助完成学术论文选题的文艺之旅
学境思源,一键生成论文初稿: AcademicIdeas - 学境思源AI论文写作 昨天我们为大家介绍了ChatGPT辅助完成实现设计(AI与学术的交响:ChatGPT辅助下的实验设计新篇章)。今天我们再来看看Kimi对于论文选题都能提供哪些帮助…...
华为od-C卷200分题目4 -电脑病毒感染
华为od-C卷200分题目4 -电脑病毒感染 一个局域网内有很多台电脑,分别标注为0 - N-1的数字。相连接的电脑距离不一样,所以感染时间不一样,感染时间用t表示。其中网络内一个电脑被病毒感染,其感染网络内所有的电脑需要最少需要多长…...

show-overflow-tooltip 解决elementui el-table标签自动换行的问题
elementui中 el-table中某一行的高度不想因为宽度不够而撑开换行展示的解决方法。可通过show-overflow-tooltip属性解决,如下 代码是这样的 <el-table-column width"80" prop"id" label"ID"></el-table-column> <el…...
浏览器访问 AWS ECS 上部署的 Docker 容器(监听 80 端口)
✅ 一、ECS 服务配置 Dockerfile 确保监听 80 端口 EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]或 EXPOSE 80 CMD ["python3", "-m", "http.server", "80"]任务定义(Task Definition&…...
【位运算】消失的两个数字(hard)
消失的两个数字(hard) 题⽬描述:解法(位运算):Java 算法代码:更简便代码 题⽬链接:⾯试题 17.19. 消失的两个数字 题⽬描述: 给定⼀个数组,包含从 1 到 N 所有…...

CMake基础:构建流程详解
目录 1.CMake构建过程的基本流程 2.CMake构建的具体步骤 2.1.创建构建目录 2.2.使用 CMake 生成构建文件 2.3.编译和构建 2.4.清理构建文件 2.5.重新配置和构建 3.跨平台构建示例 4.工具链与交叉编译 5.CMake构建后的项目结构解析 5.1.CMake构建后的目录结构 5.2.构…...
在四层代理中还原真实客户端ngx_stream_realip_module
一、模块原理与价值 PROXY Protocol 回溯 第三方负载均衡(如 HAProxy、AWS NLB、阿里 SLB)发起上游连接时,将真实客户端 IP/Port 写入 PROXY Protocol v1/v2 头。Stream 层接收到头部后,ngx_stream_realip_module 从中提取原始信息…...

微信小程序 - 手机震动
一、界面 <button type"primary" bindtap"shortVibrate">短震动</button> <button type"primary" bindtap"longVibrate">长震动</button> 二、js逻辑代码 注:文档 https://developers.weixin.qq…...

Springcloud:Eureka 高可用集群搭建实战(服务注册与发现的底层原理与避坑指南)
引言:为什么 Eureka 依然是存量系统的核心? 尽管 Nacos 等新注册中心崛起,但金融、电力等保守行业仍有大量系统运行在 Eureka 上。理解其高可用设计与自我保护机制,是保障分布式系统稳定的必修课。本文将手把手带你搭建生产级 Eur…...

tree 树组件大数据卡顿问题优化
问题背景 项目中有用到树组件用来做文件目录,但是由于这个树组件的节点越来越多,导致页面在滚动这个树组件的时候浏览器就很容易卡死。这种问题基本上都是因为dom节点太多,导致的浏览器卡顿,这里很明显就需要用到虚拟列表的技术&…...

蓝桥杯3498 01串的熵
问题描述 对于一个长度为 23333333的 01 串, 如果其信息熵为 11625907.5798, 且 0 出现次数比 1 少, 那么这个 01 串中 0 出现了多少次? #include<iostream> #include<cmath> using namespace std;int n 23333333;int main() {//枚举 0 出现的次数//因…...
2023赣州旅游投资集团
单选题 1.“不登高山,不知天之高也;不临深溪,不知地之厚也。”这句话说明_____。 A、人的意识具有创造性 B、人的认识是独立于实践之外的 C、实践在认识过程中具有决定作用 D、人的一切知识都是从直接经验中获得的 参考答案: C 本题解…...

Razor编程中@Html的方法使用大全
文章目录 1. 基础HTML辅助方法1.1 Html.ActionLink()1.2 Html.RouteLink()1.3 Html.Display() / Html.DisplayFor()1.4 Html.Editor() / Html.EditorFor()1.5 Html.Label() / Html.LabelFor()1.6 Html.TextBox() / Html.TextBoxFor() 2. 表单相关辅助方法2.1 Html.BeginForm() …...