【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࿰…...
23-Oracle 23 ai 区块链表(Blockchain Table)
小伙伴有没有在金融强合规的领域中遇见,必须要保持数据不可变,管理员都无法修改和留痕的要求。比如医疗的电子病历中,影像检查检验结果不可篡改行的,药品追溯过程中数据只可插入无法删除的特性需求;登录日志、修改日志…...
多模态商品数据接口:融合图像、语音与文字的下一代商品详情体验
一、多模态商品数据接口的技术架构 (一)多模态数据融合引擎 跨模态语义对齐 通过Transformer架构实现图像、语音、文字的语义关联。例如,当用户上传一张“蓝色连衣裙”的图片时,接口可自动提取图像中的颜色(RGB值&…...
(二)原型模式
原型的功能是将一个已经存在的对象作为源目标,其余对象都是通过这个源目标创建。发挥复制的作用就是原型模式的核心思想。 一、源型模式的定义 原型模式是指第二次创建对象可以通过复制已经存在的原型对象来实现,忽略对象创建过程中的其它细节。 📌 核心特点: 避免重复初…...
如何为服务器生成TLS证书
TLS(Transport Layer Security)证书是确保网络通信安全的重要手段,它通过加密技术保护传输的数据不被窃听和篡改。在服务器上配置TLS证书,可以使用户通过HTTPS协议安全地访问您的网站。本文将详细介绍如何在服务器上生成一个TLS证…...
C# 求圆面积的程序(Program to find area of a circle)
给定半径r,求圆的面积。圆的面积应精确到小数点后5位。 例子: 输入:r 5 输出:78.53982 解释:由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982,因为我们只保留小数点后 5 位数字。 输…...
如何在网页里填写 PDF 表格?
有时候,你可能希望用户能在你的网站上填写 PDF 表单。然而,这件事并不简单,因为 PDF 并不是一种原生的网页格式。虽然浏览器可以显示 PDF 文件,但原生并不支持编辑或填写它们。更糟的是,如果你想收集表单数据ÿ…...
Java线上CPU飙高问题排查全指南
一、引言 在Java应用的线上运行环境中,CPU飙高是一个常见且棘手的性能问题。当系统出现CPU飙高时,通常会导致应用响应缓慢,甚至服务不可用,严重影响用户体验和业务运行。因此,掌握一套科学有效的CPU飙高问题排查方法&…...
管理学院权限管理系统开发总结
文章目录 🎓 管理学院权限管理系统开发总结 - 现代化Web应用实践之路📝 项目概述🏗️ 技术架构设计后端技术栈前端技术栈 💡 核心功能特性1. 用户管理模块2. 权限管理系统3. 统计报表功能4. 用户体验优化 🗄️ 数据库设…...
C++.OpenGL (14/64)多光源(Multiple Lights)
多光源(Multiple Lights) 多光源渲染技术概览 #mermaid-svg-3L5e5gGn76TNh7Lq {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-3L5e5gGn76TNh7Lq .error-icon{fill:#552222;}#mermaid-svg-3L5e5gGn76TNh7Lq .erro…...
算法:模拟
1.替换所有的问号 1576. 替换所有的问号 - 力扣(LeetCode) 遍历字符串:通过外层循环逐一检查每个字符。遇到 ? 时处理: 内层循环遍历小写字母(a 到 z)。对每个字母检查是否满足: 与…...
