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

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 …...

架构是怎样练成的-楼宇监控系统案例

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

valgrind使用浅谈

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

强化学习专题:强化学习知识梳理(一)

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

深入JVM:详解JIT即时编译器

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

ORBSLAM3_ROS_Ubuntu18_04环境搭建安装

orbslam3安装 ORB-SLAM3配置及安装教程&#xff08;2023.3&#xff09;_orbslam3安装-CSDN博客 换源&#xff0c;换成国内的 搜索software 安装工具 sudo apt install git sudo apt update sudo apt install gcc g cmake安装 cmake安装新版本 ubuntu20.04安装cmake详细…...

【opencv - C++ - Ubuntu】putText 显示中文最快方法

话不多说&#xff0c;直接上代码 #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、点击三个竖点&#xff0c;再点设置 2、点击传输&#xff0c;再点击去开启该功能 3、点击同意&#xff0c;开启优化速率 三、结果 四、备注 一、背景 当你不是百度网盘会员时&#xff0c;你在使用百度网盘下载时&#xff0c;是否下载速度太…...

Python api接口 异步

Python API接口异步编程简介 在现代的软件开发中&#xff0c;大多数应用都需要通过API接口与其他系统进行交互。Python是一种非常流行的编程语言&#xff0c;因此许多开发者选择使用Python来构建他们的API接口。在一些情况下&#xff0c;API接口需要进行异步编程&#xff0c;以…...

Java 和 Kotlin 单例模式写法对比

目录 1、饿汉模式 Java 写法&#xff1a; Kotlin 写法&#xff1a; Kotlin 这段代码反编译&简化后如下&#xff1a; 2、懒汉模式&#xff0c;静态同步方法 Java 写法&#xff1a; Kotlin 写法&#xff1a; Kotlin 这段代码反编译&简化后如下&#xff1a; 3、懒…...

解析connectionReset异常的原因与解决方案

解析connectionReset异常的原因与解决方案 大家好&#xff0c;我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01;今天我们将深入探讨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 表示使用大端字节序&#xff08;从高位到低位&…...

计算机视觉 | 基于图像处理和边缘检测算法的黄豆计数实验

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

深入分析 Android BroadcastReceiver (七)

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

C++中的数据结构

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

武汉星起航:一站式服务,助力亚马逊卖家高效运营,实现收益飞跃

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

从灵感到实践:Kimi辅助完成学术论文选题的文艺之旅

学境思源&#xff0c;一键生成论文初稿&#xff1a; AcademicIdeas - 学境思源AI论文写作 昨天我们为大家介绍了ChatGPT辅助完成实现设计&#xff08;AI与学术的交响&#xff1a;ChatGPT辅助下的实验设计新篇章&#xff09;。今天我们再来看看Kimi对于论文选题都能提供哪些帮助…...

华为od-C卷200分题目4 -电脑病毒感染

华为od-C卷200分题目4 -电脑病毒感染 一个局域网内有很多台电脑&#xff0c;分别标注为0 - N-1的数字。相连接的电脑距离不一样&#xff0c;所以感染时间不一样&#xff0c;感染时间用t表示。其中网络内一个电脑被病毒感染&#xff0c;其感染网络内所有的电脑需要最少需要多长…...

show-overflow-tooltip 解决elementui el-table标签自动换行的问题

elementui中 el-table中某一行的高度不想因为宽度不够而撑开换行展示的解决方法。可通过show-overflow-tooltip属性解决&#xff0c;如下 代码是这样的 <el-table-column width"80" prop"id" label"ID"></el-table-column> <el…...

博客生成器架构设计:基于LLM与模块化流水线的自动化内容创作实践

1. 项目概述&#xff1a;一个博客生成器的诞生与价值在内容创作领域&#xff0c;效率和质量是永恒的矛盾。作为一名写了十几年博客的“老鸟”&#xff0c;我深知从灵光一闪到一篇结构清晰、排版美观的文章发布&#xff0c;中间有多少琐碎的步骤&#xff1a;构思大纲、撰写内容、…...

同态加密优化与安全字符串匹配技术解析

1. 同态加密与安全字符串匹配技术概述在现代数据隐私保护领域&#xff0c;同态加密(Homomorphic Encryption, HE)技术因其独特的"加密数据可计算"特性而备受关注。这项技术允许第三方在不解密的情况下对加密数据进行特定计算&#xff0c;计算结果解密后与对明文直接计…...

C++默认成员函数

构造函数构造函数是特殊的成员函数&#xff0c;需要注意的是&#xff0c;构造函数虽然名称叫构造&#xff0c;但是构造函数的主要任务并不是开空间创建对象(局部对象在栈帧创建时&#xff0c;空间就开好了)&#xff0c;而是对象实例化时初始化对象。构造函数的本质是要替代我们…...

终极指南:5分钟解锁小爱音箱完整音乐自由

终极指南&#xff1a;5分钟解锁小爱音箱完整音乐自由 【免费下载链接】xiaomusic 使用小爱音箱播放音乐&#xff0c;音乐使用 yt-dlp 下载。 项目地址: https://gitcode.com/GitHub_Trending/xia/xiaomusic 还在为小爱音箱的音乐限制感到困扰&#xff1f;想听什么歌都要…...

AD7606模块的两种采样模式实战对比:Buffer模式 vs Sample模式,怎么选?

AD7606模块采样模式深度解析&#xff1a;Buffer模式与Sample模式的技术抉择 在工业测量、科研实验和自动化控制领域&#xff0c;高速多通道数据采集系统扮演着至关重要的角色。AD7606作为一款16位8通道同步采样ADC芯片&#xff0c;凭借其最高200kSPS的采样率和灵活的接口设计&a…...

华大HC32F4A0驱动128kB国产EEPROM(贝岭BL25CMIA)保姆级SPI配置与读写避坑指南

华大HC32F4A0驱动128kB国产EEPROM&#xff08;贝岭BL25CMIA&#xff09;实战指南&#xff1a;SPI配置与读写优化全解析 在嵌入式系统开发中&#xff0c;大容量存储解决方案往往面临性能与可靠性的双重挑战。华大半导体的HC32F4A0系列MCU凭借其高性能SPI接口&#xff0c;成为驱…...

从冷冰冰播报到“会呼吸的语音”:ElevenLabs非正式情绪语音落地4大行业案例(客服话术/有声书/AI陪伴/短视频配音),含真实AB测试CTR提升27%数据

更多请点击&#xff1a; https://intelliparadigm.com 第一章&#xff1a;从冷冰冰播报到“会呼吸的语音”&#xff1a;ElevenLabs非正式情绪语音的技术跃迁 传统TTS系统常陷入语调扁平、节奏机械、情感缺失的困境——即便输入“我太开心了&#xff01;”&#xff0c;输出也如…...

Dify集成Voicevox:为AI应用注入日系动漫语音灵魂

1. 项目概述&#xff1a;当开源AI应用平台遇上日系语音合成最近在折腾一个AI应用&#xff0c;需要给生成的文本内容配上自然、有表现力的语音。市面上通用的TTS&#xff08;文本转语音&#xff09;服务&#xff0c;要么是千篇一律的“机器人腔”&#xff0c;要么就是价格不菲。…...

短剧低成本创业方案|轻量化H5+小程序组合,零压力快速启动项目

一、前言 现在短剧行业内卷严重&#xff0c;很多新手盲目投入资金开发APP、购买高价版权、大额投放流量&#xff0c;最后成本回不来、项目烂尾。对于普通创业者、小型流量工作室来说&#xff0c;重资产、高成本、长周期的模式早已不适合入局。 真正适合新手的玩法&#xff0c…...

告别U盘!用CentOS 7.9 + iPXE + dnsmasq搭建一个能装CentOS/AlmaLinux/Ubuntu的万能网络启动盘

告别U盘&#xff01;用CentOS 7.9 iPXE dnsmasq搭建万能网络启动环境 每次机房新设备到货或系统升级时&#xff0c;运维人员最头疼的就是反复制作不同系统的启动U盘。传统方式不仅效率低下&#xff0c;还常遇到U盘兼容性问题。本文将分享如何利用一台闲置的CentOS 7.9服务器&…...