【C++】深拷贝和浅拷贝 ② ( 默认拷贝构造函数是浅拷贝 | 代码示例 - 浅拷贝造成的问题 )
文章目录
- 一、默认拷贝构造函数是浅拷贝
- 1、默认拷贝构造函数
- 2、默认拷贝构造函数是浅拷贝机制
- 二、代码示例 - 浅拷贝造成的问题
一、默认拷贝构造函数是浅拷贝
1、默认拷贝构造函数
如果 C++ 类中 没有定义拷贝构造函数 , C++ 编译器会自动为该类提供一个 " 默认的拷贝构造函数 " , 在函数中对成员变量进行简单的复制操作 ;
" 默认拷贝构造函数 " 用于创建一个新对象作为现有对象的副本 , 其作用是将 现有对象 的成员变量 复制到 新对象中 ;
创建一个类对象 并将其 赋值给 另一个类对象时 , 会自动调用 默认拷贝构造函数 ;
2、默认拷贝构造函数是浅拷贝机制
C++ 编译器 为 类 自动生成的 默认拷贝构造函数 是 浅拷贝 , 只能拷贝 顶层的 成员变量值 , 如果成员变量 是 引用 或 指针 , 其指向的 类 或 内存空间 中的数据 , 是无法拷贝的 ;
如果 没有定义 拷贝构造函数 , 就会触发上述机制 ;
出现如下代码调用时 , 先 调用 有参构造函数 创建了一个 原始对象 s ,
然后 将 s 对象的值 赋值给 s2 对象 , 此时调用的是 拷贝构造函数 ,
由于没有定义 拷贝构造函数 , 使用的事 C++ 编译器的 默认拷贝构造函数 , 进行的拷贝 是 浅拷贝 ;
其中的 字符串指针 , 只拷贝了指针的值 , 没有拷贝字符串的具体内容 ;
// 调用有参构造函数 , 创建 Student 实例对象Student s(18, "Tom");// 声明 Student 对象 s2 , 并使用 s 为 s2 赋值// 该操作会调用 默认的拷贝构造函数 // C++ 编译器提供的拷贝构造函数 只能进行浅拷贝Student s2 = s;
二、代码示例 - 浅拷贝造成的问题
下面代码中 ,
定义的 Student 类 中 , 定义了 有参构造函数 和 析构函数 ,
没有定义拷贝构造函数 , 因此 C++ 编译器为其生成了 默认拷贝构造函数 ,
默认拷贝构造函数 是 浅拷贝 ;
分析下面 创建两个 Student 对象 的代码 :
// 调用有参构造函数 , 创建 Student 实例对象Student s(18, "Tom");// 打印 Student 实例对象成员变量值s.toString();// 声明 Student 对象 s2 , 并使用 s 为 s2 赋值// 该操作会调用 默认的拷贝构造函数 // C++ 编译器提供的拷贝构造函数 只能进行浅拷贝Student s2 = s;s2.toString();
Student s(18, "Tom") 是调用有参参构造函数 , 创建 Student 实例对象 , 并调用 s.toString() 打印上述对象 , 打印结果为 :
m_age = 18 , m_name = Tom
Student s2 = s 代码中 , 声明 Student 对象 s2 , 并使用 s 为 s2 赋值 , 该操作会调用 默认的拷贝构造函数 , C++ 编译器提供的拷贝构造函数 只能进行浅拷贝 , 因此打印的值是一样的 ;
m_age = 18 , m_name = Tom
分析修改 拷贝对象 代码 :
// 修改 s2 对象strcpy(s2.m_name, "Jey");s.toString();s2.toString();
strcpy(s2.m_name, "Jey") 代码中 , 修改了 拷贝对象 指针指向的内容 , 将 “Tom” 改为了 “Jey” , 修改了指针指向的内容之后 , 拷贝对象 和 原始对象 的 m_name 成员值都变成了 “Jey” ;
拷贝对象 和 原始对象 都使用了相同的指针 , 那么在析构时就需要注意 , 不能重复 free 掉相同的指针 , 否则就会报错 ;
代码示例 :
#define _CRT_SECURE_NO_WARNINGS#include "iostream"
using namespace std;class Student
{
public:// 有参构造函数Student(int age, const char* name){// 获取字符串长度int len = strlen(name);// 为 m_name 成员分配内存 // 注意还要为字符串结尾的 '\0' 字符分配内存m_name = (char*)malloc(len + 1);// 拷贝字符串// C++ 中使用该函数需要// 添加 #define _CRT_SECURE_NO_WARNINGS 宏定义if (m_name != NULL){strcpy(m_name, name);}// 为 m_age 成员设置初始值m_age = age;cout << "调用有参构造函数" << endl;}~Student(){// 销毁 name 指向的堆内存空间if (m_name != NULL){free(m_name);m_name = NULL;}cout << "调用析构函数" << endl;}// 该类没有定义拷贝构造函数 , C++ 编译器会自动生成默认的拷贝构造函数// 打印类成员变量void toString(){cout << "m_age = " << m_age << " , m_name = " << m_name << endl;}public:int m_age;char* m_name;
};int main()
{// 调用有参构造函数 , 创建 Student 实例对象Student s(18, "Tom");// 打印 Student 实例对象成员变量值s.toString();// 声明 Student 对象 s2 , 并使用 s 为 s2 赋值// 该操作会调用 默认的拷贝构造函数 // C++ 编译器提供的拷贝构造函数 只能进行浅拷贝Student s2 = s;s2.toString();// 修改 s2 对象strcpy(s2.m_name, "Jey");s.toString();s2.toString();// 执行时没有问题 , 两个对象都可以正常访问// 但是由于拷贝时 执行的是浅拷贝 // 浅拷贝 字符串指针时 , 直接将指针进行拷贝 , 没有拷贝具体的值// s 和 s2 的 m_name 成员是同一个指针// 如果析构时 , 先析构 s2 , 将指针释放了 // 之后再析构 s 时 发现 继续释放 被释放的指针 , 报错了// 控制台暂停 , 按任意键继续向后执行system("pause");return 0;
}
执行结果 : 执行后打印如下内容 ,
调用有参构造函数
m_age = 18 , m_name = Tom
m_age = 18 , m_name = Tom
m_age = 18 , m_name = Jey
m_age = 18 , m_name = Jey
请按任意键继续. . .

按下任意键 , 继续向后执行 , 调用完第一个析构函数后 , 再次尝试调用第二个析构函数 , 报错了 ;

相关文章:
【C++】深拷贝和浅拷贝 ② ( 默认拷贝构造函数是浅拷贝 | 代码示例 - 浅拷贝造成的问题 )
文章目录 一、默认拷贝构造函数是浅拷贝1、默认拷贝构造函数2、默认拷贝构造函数是浅拷贝机制 二、代码示例 - 浅拷贝造成的问题 一、默认拷贝构造函数是浅拷贝 1、默认拷贝构造函数 如果 C 类中 没有定义拷贝构造函数 , C 编译器会自动为该类提供一个 " 默认的拷贝构造函…...
【Selenium】webdriver.ChromeOptions()官方文档参数
Google官方Chrome文档,在此记录一下 Chrome Flags for Tooling Many tools maintain a list of runtime flags for Chrome to configure the environment. This file is an attempt to document all chrome flags that are relevant to tools, automation, benchm…...
pytorch代码实现之动态卷积模块ODConv
ODConv动态卷积模块 ODConv可以视作CondConv的延续,将CondConv中一个维度上的动态特性进行了扩展,同时了考虑了空域、输入通道、输出通道等维度上的动态性,故称之为全维度动态卷积。ODConv通过并行策略采用多维注意力机制沿核空间的四个维度…...
动态规划:子序列问题(C++)
动态规划:子序列问题 前言子序列问题1.最长递增子序列(中等)2.摆动序列(中等)3.最长递增子序列的个数(中等)4.最长数对链(中等)5.最长定差子序列(中等&#x…...
ORACLE的分区(一)
目录 一、分区概念 二、表分区的优点 三、分区策略 一、分区概念 随着时间的发展,一个表的数据会越来越多,当数据量增大的时候我们一般采取建立索引优化索引的方式提高查询速度,但是数据量再次增大即使是索引也无法提高速度,这时…...
【数据结构】C++实现二叉搜索树
二叉搜索树的概念 二叉搜索树又称为二叉排序树,它或者是一棵空树,或者是具有以下性质的二叉树: 若它的左子树不为空,则左子树上所有结点的值都小于根结点的值。若它的右子树不为空,则右子树上所有结点的值都大于根结…...
Python中Mock和Patch的区别
前言: 嗨喽~大家好呀,这里是魔王呐 ❤ ~! python更多源码/资料/解答/教程等 点击此处跳转文末名片免费获取 在测试并行开发(TPD)中,代码开发是第一位的。 尽管如此,我们还是要写出开发的测试,…...
sql server 查询某个字段是否有值 返回bool类型
sql server 查询某个字段是否有值 返回bool类型,true 或 false SELECT ColumnCode,CONVERT(BIT,CASE WHEN LEN(ColumnCode) > 0 THEN 1 ELSE 0 END) AS HasValue FROM dbo.TF_LessonCatalog...
紫光展锐5G芯T820 解锁全新应用场景,让机器人更智能
数字经济的持续发展正推动机器人产业成为风口赛道。工信部数据显示,2023年上半年,我国工业机器人产量达22.2万套,同比增长5.4%;服务机器人产量为353万套,同比增长9.6%。 作为国内商用服务机器人领先企业,云…...
秋招前端面试题总结
1、this指向问题,以前总是迷糊,现在总算是一知半解了。应当遵循以下原则,应该就能做对题目了。 如果一个标准函数,也就是非箭头函数,作为某个对象的方法被调用时,那么这个this指向的就是这个对象。涉及到闭…...
【入门篇】ClickHouse 数据类型
文章目录 1. 引言2. ClickHouse 数据类型2.1 基本数据类型2.1.1 整型2.1.2 浮点型2.1.3 字符串型 2.2 复合数据类型2.2.1 数组2.2.2 枚举类型2.2.3 元组2.2.4 Map2.2.5 Nullable 2.3 特殊数据类型2.3.1 日期和时间类型2.3.2 UUID2.3.3 IP 地址2.3.4 AggregateFunction 2.4 数据…...
关于Python数据分析,这里有一条高效的学习路径
无处不在的数据分析 谷歌的数据分析可以预测一个地区即将爆发的流感,从而进行针对性的预防;淘宝可以根据你浏览和消费的数据进行分析,为你精准推荐商品;口碑极好的网易云音乐,通过其相似性算法,为不同的人…...
基于 json-server 工具,模拟实现后端接口服务环境
文章目录 本地配置后端接口一、安装json-server1、安装 JSON 服务器 安装 JSON 服务器2、创建一个db.json包含一些数据的文件(重点)3、启动 JSON 服务器 启动 JSON 服务器4、现在如果你访问http://localhost:3000/posts/1,你会得到 本地配置后…...
想要精通算法和SQL的成长之路 - 课程表II
想要精通算法和SQL的成长之路 - 课程表 前言一. 课程表II (拓扑排序)1.1 拓扑排序1.2 题解 前言 想要精通算法和SQL的成长之路 - 系列导航 一. 课程表II (拓扑排序) 原题链接 1.1 拓扑排序 核心知识: 拓扑排序是专…...
【sgGoogleTranslate】自定义组件:基于Vue.js用谷歌Google Translate翻译插件实现网站多国语言开发
sgGoogleTranslate源码 <template><div :id"$options.name"> </div> </template> <script> export default {name: "sgGoogleTranslate",props: ["languages", "currentLanguage"],data() {return {//…...
论文总结《A Closer Look at Few-shot Classification Again》
原文链接 A Closer Look at Few-shot Classification Again 摘要 这篇文章主要探讨了在少样本图像分类问题中,training algorithm 和 adaptation algorithm的相关性问题。给出了training algorithm和adaptation algorithm是完全不想关的,这意味着我们…...
Postman使用_参数设置和获取
文章目录 参数引用内置动态参数手动添加参数脚本设置参数脚本获取参数 参数就像变量一样,它可以是固定的值,也可以是变化的值,比如:会根据一些条件或其他参数进行变化。我们如果要使用该参数就需要引用它。 参数引用 引用动态参数…...
【SQL】优化SQL查询方法
优化SQK查询 一、避免全表扫描 1、where条件中少使用! 或 <>操作符,引擎会放弃索引,进行全表扫描 2、in \or ,用between 或 exist 代替in 3、where 对字段进行为空判断 4、where like ‘%条件’ 前置百分号 5、where …...
Linux-相关操作
2.2.2 Linux目录结构 /:根目录,一般根目录下只存放目录,在Linux下有且只有一个根目录。所有的东西都是从这里开始。当你在终端里输入“/home”,你其实是在告诉电脑,先从/(根目录)开始…...
二十、MySQL多表关系
1、概述 在项目开发中,在进行数据库表结构设计时,会根据业务需求以及业务模块之间的关系,分析并设计表结构,由于业务之间相互关联,所以各个表结构之间也存在着各种对应关系 2、多表关系分类 (1࿰…...
Delphi 终极实战:将自定义控件打包成 BPL,安装到 Delphi 工具栏(组件库实战)
前面我们手写了专属 UI 组件库(MyUIClass.pas),但如果你想在以后的项目中一键调用这些控件,而不是每次都复制粘贴代码,那就必须将它们打包成 Delphi 组件包(BPL 文件)。学会这篇,你将…...
造相-Z-Image-Turbo亚洲美女LoRA创作实战:三个案例教你玩转AI绘画
造相-Z-Image-Turbo亚洲美女LoRA创作实战:三个案例教你玩转AI绘画 1. 认识造相-Z-Image-Turbo与亚洲美女LoRA 造相-Z-Image-Turbo是一款强大的AI图片生成模型,而亚洲美女LoRA则是专门针对亚洲人物特征优化的风格适配器。这个组合让普通用户也能轻松创作…...
开源像素艺术大模型教程:Pixel Dream Workshop Windows/Mac双平台部署
开源像素艺术大模型教程:Pixel Dream Workshop Windows/Mac双平台部署 1. 像素幻梦创意工坊简介 Pixel Dream Workshop(像素幻梦创意工坊)是一款基于FLUX.1-dev扩散模型的像素艺术生成工具。它采用独特的16-bit像素风格界面设计,…...
ChatBI 开源产品实战解析:从语义层到Agent,如何选择你的AI数据助手?
1. 为什么企业需要AI数据助手? 想象一下这个场景:市场部的小王需要统计上季度各区域的销售数据,他对着Excel表格里密密麻麻的数字发愁,不得不找IT部门帮忙写SQL查询。三天后拿到数据时,业务窗口期已经错过——这是很多…...
告别蓝牙!用STM32F103和NRF24L01搭建低成本2.4G无线通信,实测传输距离与稳定性
STM32F103与NRF24L01构建高性能2.4G私有通信系统实战指南 在物联网设备爆发式增长的今天,无线通信模块的选择成为硬件开发者面临的首要难题。面对市面上琳琅满目的蓝牙、Wi-Fi和私有协议模块,如何根据项目需求选择最具性价比的解决方案?本文将…...
Vivado仿真踩坑实录:PR模式不支持仿真的快速解决方案(附详细步骤)
Vivado仿真避坑指南:PR模式不支持仿真的深度解析与实战方案 刚接触FPGA开发的朋友们,不知道你们是否遇到过这样的场景:在Vivado中精心设计了一个工程,准备进行仿真验证时,突然弹出一个令人困惑的错误提示——"Sim…...
Polars 2.0内存优化实战:如何用lazy().collect()规避OOM,单机处理500GB脏数据?
第一章:Polars 2.0内存优化实战:如何用lazy().collect()规避OOM,单机处理500GB脏数据?在处理超大规模脏数据集时,传统 eager 模式极易触发 OOM(Out-of-Memory)错误。Polars 2.0 的 LazyFrame 提…...
Qt5新手必看:3分钟搞定你的第一个控制台程序(附完整代码)
Qt5入门实战:从零构建控制台应用的完整指南 引言:为什么选择Qt5作为开发起点? 对于刚接触C图形界面开发的程序员来说,Qt框架提供了一个绝佳的起点。它不仅拥有跨平台特性,还具备完善的工具链和丰富的模块库。控制台程序…...
别再手动填Token了!用Knife4j的OAuth2配置,一键搞定接口文档自动化认证
告别手动Token时代:Knife4j与OAuth2的自动化认证实战 每次调试API都要复制粘贴Token的日子该结束了。作为后端开发者,我们花了大量时间在接口文档和认证流程之间来回切换——这不仅是效率问题,更是一种思维中断。想象一下,当你的微…...
基于ANPC型三电平逆变器的VSG并网及参数自适应控制
ANPC虚拟同步机(VSG)并网(参数自适应控制),基于ANPC型三电平逆变器的参数自适应控制,采用电压电流双闭环控制,中点电位平衡控制,且实现VSG并网。 1.VSG参数自适应 2.VSG并网 3.提供相…...
