好问题 👍,这个就是理解 = delete 的关键前置知识。
我从 C语言基础 出发,像教科书一样,从零讲给你听。


1. 什么是“拷贝”?

在 C++ 中,当你有一个对象 A,然后写:

Device_Info a;
Device_Info b = a;   // 或者 b(a);

这就是在“拷贝一个对象”。
系统会帮你把 a 的内容复制到 b 里,这个过程叫做 拷贝构造

同样地,如果写:

Device_Info c;
c = a;   // 已经存在的对象 c,用 a 的内容覆盖它

这就是“拷贝赋值”。


2. 浅拷贝(Shallow Copy)

👉 定义:只复制“表面数据”,也就是 成员变量的值

举个例子:

struct Data {int* ptr;
};Data a;
a.ptr = new int(42);   // a 里面的指针指向堆上的一个整数Data b = a;   // 系统默认的拷贝(浅拷贝)

这时候 a.ptrb.ptr 指向同一块内存

  • 修改 *a.ptr 会影响 *b.ptr
  • 如果两个对象都去 delete ptr; → 就会出现 二次释放(double free) 错误。

👉 这就是浅拷贝的风险。


3. 深拷贝(Deep Copy)

👉 定义:不光复制指针的值,还会 分配一块新的内存,并复制数据内容

改写上面的例子:

struct Data {int* ptr;// 自己实现拷贝构造函数(深拷贝)Data(const Data& other) {ptr = new int(*other.ptr); // 新开一块内存,复制内容}
};

这样 a.ptrb.ptr 各自独立:

  • 改变 a 不会影响 b
  • 各自释放时也不会冲突。

4. 为什么要禁用拷贝?(= delete)

有些类(比如你说的 Device_Info)是全局单例,不能被“复制”出新对象。

如果你允许浅拷贝:

  • 很可能复制出来多个“全局唯一”的对象,状态混乱。

如果你允许深拷贝:

  • 逻辑上也没意义:全局设备信息只有一份,复制出来的副本没法保持同步。

👉 所以直接禁用拷贝:

Device_Info(const Device_Info&) = delete;       // 禁用拷贝构造
Device_Info& operator=(const Device_Info&) = delete; // 禁用拷贝赋值

这样一来,编译器遇到下面的代码时就会报错:

Device_Info a;
Device_Info b = a;   // ❌ 编译错误
Device_Info c;
c = a;               // ❌ 编译错误

保证了你的 Device_Info 只有一个实例,不会被复制。


一句话总结

  • 浅拷贝 = 复制指针值 → 多个对象共享同一资源(风险大)。
  • 深拷贝 = 复制指针指向的内容 → 每个对象都有独立资源(安全,但开销大)。
  • = delete = 禁止拷贝 → 防止“本不该复制的对象”被复制(最安全)。

要不要我给你画个“浅拷贝 vs 深拷贝”的图解,形象一点?




好👌 那我从 C 角度 慢慢过渡到 C++ 浅拷贝 / 深拷贝,让你完全能理解。


1. C 里拷贝变量

在 C 里,我们写:

int a = 10;
int b = a;  // 把 a 的值拷贝到 b

这里 b 得到的是一个独立的副本,修改 b 不会影响 a
这就相当于 值的复制


2. 指针和数组的情况

再来看指针或数组:

char *p = malloc(10);
char *q = p;   // q 和 p 指向同一块内存

现在 pq 共享一块内存。如果你通过 q 修改数据,p 看到的也会变。
这就不是复制内容,而是复制了“地址” → 浅拷贝


3. 到 C++ 的对象

在 C++ 里,对象可以有很多成员(比如内存指针、数组、文件句柄等)。
当你写:

Device_Info a;
Device_Info b = a;  // 调用拷贝构造函数

编译器默认会帮你“一个字段一个字段”地复制 → 浅拷贝

  • 如果对象里有普通的 int、double,这没问题。
  • 如果对象里有指针,那就危险了!因为两个对象的指针会指向同一块内存,可能导致 二次释放 (double free)悬空指针

4. 浅拷贝 vs 深拷贝

浅拷贝(shallow copy)

只复制“指针的值”,不复制指针指向的内容。
结果:多个对象共享同一块资源。

例子:

struct A {int *data;
};
A a;
a.data = new int(5);A b = a;   // 浅拷贝:b.data 和 a.data 指向同一块内存

这样当 abdelete data 时就会崩溃。


深拷贝(deep copy)

不但复制指针的值,还复制一份独立的内容。
结果:每个对象有自己独立的资源。

例子:

struct A {int *data;// 自己实现拷贝构造函数A(const A& other) {data = new int(*other.data); // 复制一份内容}
};

这样 ab 各自有自己的内存,互不影响。


5. 为什么要 = delete

有时候我们觉得拷贝很危险(比如全局唯一的资源),
干脆禁止拷贝,写:

Device_Info& operator=(const Device_Info&) = delete;

意思是:禁止拷贝赋值,编译器一旦遇到 a = b 就会报错。
这就是一种防止“浅拷贝出错”的安全写法。


📌 总结:

  • 浅拷贝:只复制指针本身,多个对象共享一块资源 → 可能危险。
  • 深拷贝:复制指针指向的内容,每个对象有自己的资源 → 安全但需要写代码实现。
  • 禁用拷贝 (= delete):当资源不能被复制时(比如全局唯一对象),直接禁止。

要不要我给你写一个小的 C 风格 vs C++ 浅拷贝 vs 深拷贝的完整对比代码,你直接跑一下就能看到区别?


深拷贝案例

好的,我们用一个 非常简单的例子 来说明浅拷贝和深拷贝的区别,不涉及图像,只用一个 int* 指针就够了。


例子:管理一个整数的类

#include <iostream>class MyInt {
public:int* value;// 构造函数MyInt(int v) {value = new int(v);}// 析构函数~MyInt() {delete value;}// 深拷贝构造函数MyInt(const MyInt& other) {value = new int(*other.value); // 申请新内存,复制内容}void print() {std::cout << *value << std::endl;}
};int main() {MyInt a(10);MyInt b = a; // 调用深拷贝构造函数a.print(); // 10b.print(); // 10*a.value = 20; // 修改 aa.print();     // 20b.print();     // 10(b 不受影响)return 0;
}

🔹 分析

  1. a.valueb.value 各自指向独立内存
  2. 修改 a.value 不会影响 b.value
  3. 析构时安全,不会 double free

如果去掉深拷贝构造函数,默认的拷贝构造是浅拷贝:

MyInt(const MyInt& other) = default;

结果就是:

  • a.valueb.value 指向同一块内存
  • 修改 a 会影响 b
  • 两个对象析构时都会 delete 同一块内存 → 崩溃

这个例子非常直观,用一个指针就能理解浅拷贝、深拷贝的区别


如果你需要,我可以帮你画一张 指针指向的内存图,形象展示浅拷贝和深拷贝的区别,让你一眼就明白。

你想让我画吗?

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/news/919545.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/919545.shtml
英文地址,请注明出处:http://en.pswp.cn/news/919545.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Arkts加载网页url的pdf发票黑屏问题

使用模拟器会闪退&#xff0c;连接真机预览正常import { HMRouter, HMRouterMgr, HMParamType, HMPageParam } from "hadss/hmrouter"; import { BaseTitle, RouterConstants } from "commonlib"; import { webview } from kit.ArkWeb; import { PDFView }…

使用 mongosh 设置 MongoDB 账号密码

可以使用 mongosh(MongoDB 6.0+ 的现代Shell)来设置账号密码。mongosh 是官方推荐的新一代MongoDB Shell工具,替代了传统的 mongo 命令。 【本人博文提到的ip均为随机生成的,不是实际的ip,仅供参考,如有雷同,纯属巧合】 使用 mongosh 设置 MongoDB 账号密码 1. 首先连…

HTML+CSS:浮动详解

在HTMLCSS布局中&#xff0c;浮动&#xff08;float&#xff09; 是一种经典的布局技术&#xff0c;用于控制元素在页面中的排列方式。它最初设计用于实现文字环绕图片的效果&#xff0c;后来被广泛用于复杂布局&#xff0c;但随着Flexbox和Grid的兴起&#xff0c;其使用场景有…

GPIO初始化及调用

下面把 HAL 库 和 标准外设库&#xff08;SPL&#xff09; 初始化 GPIO 点亮/熄灭 LED 的完整步骤、示例代码和常用 API 逐一说清楚。用例默认 PC13 接 LED&#xff08;蓝板常见&#xff1b;低电平点亮&#xff0c;高电平熄灭——若板子相反&#xff0c;只把写 1/0 对调即可&am…

【GPT入门】第48课 LlamaFacotory 合并原模型与LoRA模型

【GPT入门】第48课 LlamaFacotory 合并原模型与LoRA模型1.合并原模型与LoRA训练的增量模型2. 测试模型1.合并原模型与LoRA训练的增量模型 llamafactory-cli webui 执行合并 合并后模型大小 (base) rootautodl-container-b4b04ea4f2-b5ee47d1:~# du -sh /root/autodl-tmp/mod…

Python爬虫实战:研究tumblr,构建博客平台数据采集分析系统

1. 引言 1.1 研究背景 在信息爆炸的时代,社交媒体平台已成为人们获取信息、表达观点和进行社交互动的主要渠道。这些平台上积累的海量数据包含了用户偏好、社会趋势、文化现象等丰富信息,对学术研究、市场分析、产品开发等领域具有重要价值。 Tumblr 作为一个综合性的轻博客…

集成算法学习总结

一、集成学习基础认知 核心思想&#xff1a;集成学习&#xff08;ensemble learning&#xff09;通过构建并结合多个个体学习器来完成学习任务&#xff0c;类似于 “多个专家共同决策”&#xff0c;通常比单个学习器的性能更优。其核心逻辑是利用多个学习器的优势互补&#xff…

线程安全的产生以及解决方案

线程安全原子性&#xff08;Atomicity&#xff09;、可见性&#xff08;Visibility&#xff09;、有序性&#xff08;Ordering&#xff09; 是保证线程安全的三大核心要素 —— 线程安全问题的本质&#xff0c;几乎都是这三个特性中的一个或多个被破坏导致的。操作不会被 “中途…

Spring Cloud Netflix学习笔记01

文章目录前言一、微服务概述什么是微服务&#xff1f;微服务与微服务架构微服务优缺点优点缺点微服务技术栈有那些&#xff1f;二.SpringCloud入门概述SpringCloud是什么&#xff1f;SpringCloud和SpringBoot的关系Dubbo 和 SpringCloud技术选型总结SpringCloud能干嘛&#xff…

专题:2025母婴行业消费洞察与分龄营养趋势报告|附40 +份报告PDF、交互图表数据汇总下载

原文链接&#xff1a;https://tecdat.cn/?p43654 当95后妈妈拿着计算器对比DHA纯度&#xff0c;当爸爸们为“防红屁屁纸尿裤”货比三家&#xff0c;母婴行业的风向早就变了。从“一把奶粉喂到3岁”到“按月龄定制营养包”&#xff0c;从“进口就好”到“看专利数据下单”&…

redhat6/centos6 配置yum源

由于RHEL6/centos6系统官方早就停止通知维护了&#xff0c;公司的开发服务器有比较老&#xff0c;发现竟然scp都没有装。。。今天配置个本地yum源&#xff0c;安装一下常规软件和开发环境比较简单&#xff0c;直接上代码1.上传一个centos6的iso文件CentOS-6.5-x86_64-bin-DVD1.…

day31 SQLITE

数据库相关函数数据库创建int sqlite3_open( const char *filename, sqlite3 **ppDb);功能&#xff1a;打开数据库&#xff0c;不存在则创建参数&#xff1a;const char *filename 数据库名sqlite3 **ppDb 二级指针&#xff0c;传出ppDb数据库的一级指…

嵌入式-SPI番外之按钮驱动程序的编写-Day15

目录 一、按钮简单操作回忆 二、按钮新操作实现 &#xff08;1&#xff09;按钮的点击实现灯亮/灭 ①连接电路 ②初始化板载LED和按钮 ③按钮程序的基本原理&#xff08;核心仍为0亮/1灭&#xff09; ④按钮消抖的原理 三、按钮封装的操作-点击&#xff0c;双击&#xf…

星域智链科技:用科技点亮生活,以 AI 拓展无限可能

星域智链科技&#xff08;东莞市&#xff09;有限公司简介 星域智链科技&#xff08;东莞市&#xff09;有限公司&#xff0c;理念是 让科技便利生活、丰富生活&#xff0c;专注于科技、AI领域。 全场景 GPS 定位器 —— 精准追踪&#xff0c;守护安全&#xff0c;适用于车辆…

国内代理IP在SEO行业中的应用

随着互联网的快速发展&#xff0c;SEO&#xff08;搜索引擎优化&#xff09;已经成为了数字营销的重要组成部分。无论是企业还是个人站长&#xff0c;都希望通过SEO提升自己网站的排名和流量。然而&#xff0c;随着竞争的激烈&#xff0c;传统的SEO优化手段已经逐渐显现出局限性…

Linux + arm 内存屏障

ARM 硬件层的屏障指令DMB (Data Memory Barrier)&#xff1a;保证在它之前的内存访问&#xff08;符合给定域/类型&#xff09;在它之后的内存访问之前对可见性排序。常用域&#xff1a;ish&#xff08;Inner Shareable&#xff09;&#xff0c;sy&#xff08;system-wide&…

网络安全中的远程控制活动检测与防御策略

本文还有配套的精品资源&#xff0c;点击获取 简介&#xff1a;远程控制技术在IT领域中用于网络连接和设备操作&#xff0c;但同样被黑客利用进行非法入侵。端口占用情况是识别远程控制活动的关键因素&#xff0c;使用工具如"cports"可以监控这些端口。系统中未知…

UIGestureRecognizer 各个子类以及其作用

在 iOS 里&#xff0c;UIGestureRecognizer 是一个抽象基类&#xff0c;专门用来处理手势事件。它本身不能直接用&#xff0c;必须用它的 子类。这些子类分别对应常见的手势识别器。常见的 UIGestureRecognizer 子类及作用1. UITapGestureRecognizer作用&#xff1a;点击手势&a…

计算机网络 HTTPS 全流程

HTTPS 通信的全流程&#xff08;特别是 TLS 握手阶段&#xff09;中使用的三个随机数是保障安全性的核心设计&#xff0c;不能随意减少。每个随机数都承担着至关重要的安全职责。下面详细解释 HTTPS 全流程&#xff0c;并重点分析这三个随机数的作用和必要性&#xff1a;&#…

DL00271-基于YOLOv11的激光雷达LiDAR船舶目标检测含完整数据集

【CSDN推荐】基于YOLOv11的激光雷达&#xff08;LiDAR&#xff09;船舶目标检测——含完整数据集&#xff01;&#x1f6a2; 科研人员必看&#xff01; 高校老师、学生和研究者们&#xff0c;前沿技术来了&#xff01;本论文利用YOLOv11模型&#xff0c;结合激光雷达&#xff0…