news 2026/7/27 23:56:47

浅拷贝和深拷贝两种不同的对象复制

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
浅拷贝和深拷贝两种不同的对象复制

浅拷贝和深拷贝两种不同的对象复制

在软件开发中,对象复制是一个常见且重要的操作。无论你是在处理数据结构、传递参数,还是实现缓存,理解如何正确地复制对象都至关重要。然而,许多开发者对浅拷贝(Shallow Copy)和深拷贝(Deep Copy)的区别感到困惑,甚至在实际编码中踩坑。本文将从实战角度出发,通过大量代码示例,深入浅出地解析这两种复制方式,帮助你避免常见的陷阱。## 什么是对象复制?在编程中,对象复制指的是创建一个新对象,该对象的内容与原始对象相同。但根据复制的方式不同,结果可能大相径庭。浅拷贝只复制对象的引用,而深拷贝则递归地复制所有嵌套对象。理解这一点是关键,因为错误的选择可能导致数据共享或意外修改。## 浅拷贝:只复制一层浅拷贝是最简单的复制方式。它创建一个新对象,然后将原始对象的属性值复制到新对象中。如果属性是基本类型(如整数、字符串),则复制的是值;如果属性是引用类型(如列表、字典),则复制的是引用(即内存地址)。这意味着新对象和原始对象共享相同的子对象。### 实战示例:Python中的浅拷贝Python 提供了多种浅拷贝方式,如使用copy.copy()或直接调用对象的copy()方法(如果支持)。下面是一个完整的可运行示例。pythonimport copy# 定义一个包含嵌套结构的类class Person: def __init__(self, name, hobbies): self.name = name self.hobbies = hobbies # 这是一个列表,属于引用类型 def __repr__(self): return f"Person(name={self.name}, hobbies={self.hobbies})"# 创建原始对象original_person = Person("Alice", ["reading", "swimming", "coding"])print("原始对象:", original_person)# 使用浅拷贝创建新对象shallow_copy_person = copy.copy(original_person)print("浅拷贝对象:", shallow_copy_person)# 修改原始对象的嵌套列表original_person.hobbies.append("dancing")print("\n修改原始对象后:")print("原始对象:", original_person)print("浅拷贝对象:", shallow_copy_person)# 验证是否共享引用print("\n原始对象的 hobbies 地址:", id(original_person.hobbies))print("浅拷贝对象的 hobbies 地址:", id(shallow_copy_person.hobbies))输出结果:原始对象: Person(name=Alice, hobbies=['reading', 'swimming', 'coding'])浅拷贝对象: Person(name=Alice, hobbies=['reading', 'swimming', 'coding'])修改原始对象后:原始对象: Person(name=Alice, hobbies=['reading', 'swimming', 'coding', 'dancing'])浅拷贝对象: Person(name=Alice, hobbies=['reading', 'swimming', 'coding', 'dancing'])原始对象的 hobbies 地址: 1401234567890浅拷贝对象的 hobbies 地址: 1401234567890注释:从输出可以看出,浅拷贝只复制了Person对象本身,但hobbies列表的引用被共享了。当你修改原始对象的hobbies列表时,浅拷贝对象也受到了影响。这是因为浅拷贝没有递归复制嵌套对象,hobbies列表的id相同,证明它们是同一个内存对象。## 深拷贝:完全独立深拷贝则不同,它递归地复制所有嵌套对象,创建一个完全独立的副本。这意味着新对象和原始对象没有任何共享引用,修改一个不会影响另一个。深拷贝通常通过copy.deepcopy()实现。### 实战示例:Python中的深拷贝继续使用上面的Person类,这次我们改用深拷贝。pythonimport copy# 定义相同的 Person 类(为了完整性,重复定义)class Person: def __init__(self, name, hobbies): self.name = name self.hobbies = hobbies def __repr__(self): return f"Person(name={self.name}, hobbies={self.hobbies})"# 创建原始对象original_person = Person("Bob", ["gaming", "music"])print("原始对象:", original_person)# 使用深拷贝创建新对象deep_copy_person = copy.deepcopy(original_person)print("深拷贝对象:", deep_copy_person)# 修改原始对象的嵌套列表original_person.hobbies.append("sports")print("\n修改原始对象后:")print("原始对象:", original_person)print("深拷贝对象:", deep_copy_person)# 验证是否独立print("\n原始对象的 hobbies 地址:", id(original_person.hobbies))print("深拷贝对象的 hobbies 地址:", id(deep_copy_person.hobbies))# 修改深拷贝对象的嵌套列表(不影响原始对象)deep_copy_person.hobbies.append("art")print("\n修改深拷贝对象后:")print("原始对象:", original_person)print("深拷贝对象:", deep_copy_person)输出结果:原始对象: Person(name=Bob, hobbies=['gaming', 'music'])深拷贝对象: Person(name=Bob, hobbies=['gaming', 'music'])修改原始对象后:原始对象: Person(name=Bob, hobbies=['gaming', 'music', 'sports'])深拷贝对象: Person(name=Bob, hobbies=['gaming', 'music'])原始对象的 hobbies 地址: 1409876543210深拷贝对象的 hobbies 地址: 1409876543220修改深拷贝对象后:原始对象: Person(name=Bob, hobbies=['gaming', 'music', 'sports'])深拷贝对象: Person(name=Bob, hobbies=['gaming', 'music', 'art'])注释:这里深拷贝创建了一个全新的hobbies列表(注意地址不同),因此修改原始对象或深拷贝对象都不会互相影响。深拷贝通过递归遍历所有嵌套对象,确保每个层级都是独立的副本。这对于复杂对象(如嵌套字典、自定义类实例)非常有用。## 浅拷贝 vs 深拷贝:实战场景选择在实际开发中,选择浅拷贝还是深拷贝取决于你的需求。以下是几个典型场景:-浅拷贝适用场景:当你只需要复制一个对象的顶层结构,且子对象不会被修改时,浅拷贝性能更好。例如,复制一个只包含基本类型的对象(如整数、字符串)或只读缓存。-深拷贝适用场景:当你需要完全独立的对象,避免意外修改时,必须用深拷贝。例如,复制用户输入数据、实现撤销功能、或处理不可变数据结构。### 性能考虑深拷贝由于需要递归复制,对于大型或复杂对象,性能开销可能较大。浅拷贝则快得多。在实际项目中,应根据数据规模权衡。例如,如果你有一个包含百万级列表的对象,深拷贝可能成为性能瓶颈。## 其他语言中的实现不同语言对浅拷贝和深拷贝的支持不同。以 Java 为例,Object.clone()默认是浅拷贝,深拷贝需要手动实现Cloneable接口并重写clone()方法。JavaScript 中,Object.assign()和展开运算符...是浅拷贝,而JSON.parse(JSON.stringify(obj))是深拷贝(但有局限性,如不支持函数和循环引用)。理解语言特性是避免错误的关键。## 总结浅拷贝和深拷贝是对象复制中的两个核心概念。浅拷贝只复制顶层对象,共享引用类型属性,适合简单场景;深拷贝递归复制所有层级,确保完全独立,适合需要数据隔离的场景。通过本文的代码示例,你可以看到这两种方式的实际效果和差异。在选择时,务必考虑数据结构和修改需求,避免因共享引用导致的 bug。记住:浅拷贝是“复制指针”,深拷贝是“复制内容”。掌握这一点,你就能在项目中游刃有余地处理对象复制问题。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/27 23:51:40

TVA数字小脑:具身智能的物理交互革命(13)

前沿技术探索:AI智能体视觉(TVA,Transformer-based Vision Agent)是依托Transformer架构与“因式智能体”理论所构建的颠覆性工业视觉技术,是集深度强化学习(DRL)、卷积神经网络(CNN…

作者头像 李华
网站建设 2026/7/27 23:48:36

四大压力传感芯体详解:原理、参数与应用

目录 一、扩散硅压阻 MEMS(工业 4-20mA 数显变送器主流) 1. 核心工作原理 2. 关键电气 / 性能参数 3. 优点 4. 缺点 5. 典型应用 6. 专用模拟前端电路方案(适配 4~36V 环路供电,RY9122 降压 3.3V 整机供电) 二…

作者头像 李华
网站建设 2026/7/27 23:42:34

金融AI生态建设:从技能库到开发者社区

从0到7个Skill:金融AI开源生态建设实录方法论:开源生态建设 | 社区运营 | 持续迭代为什么开源?2023年,我决定把14年银行数字化经验开源:初衷:知识共享:让更多人受益生态共建:集思广益…

作者头像 李华
网站建设 2026/7/27 23:42:18

港科大EMBA亚洲第6,民营企业家择校选择指南

一、择校测评导语民营企业家、企业高管选读EMBA,大多面临核心困惑:内地院校人脉深厚但国际化偏弱,境外项目视野开阔但适配性参差不齐,难以匹配企业转型、出海、数字化升级等实际发展需求。本文从全球办学排名、院校办学定位、课程…

作者头像 李华
网站建设 2026/7/27 23:39:41

零基础学pcie--访问 BAR 空间示例(让驱动真正“摸到”硬件)

目录 三、访问 BAR 空间示例(让驱动真正“摸到”硬件) 先给一句话结论(请全文背诵) 一、BAR 在驱动里的“正确形态” 二、最基本的 BAR 访问(读 / 写) 1️⃣ 写寄存器 2️⃣ 读寄存器 三、为什么不能用普通指针?(非常重要) 四、一个“FPGA Endpoint”的典型寄…

作者头像 李华