【C++指南】C++中的浅拷贝与深拷贝:深入剖析

          💓 博客主页:倔强的石头的CSDN主页 

           📝Gitee主页:倔强的石头的gitee主页

            ⏩ 文章专栏:《C++指南》

                                  期待您的关注

 

47f09392526c71b5885ec838a3ea7ffe.gif

 

目录

引言

🍃浅拷贝

基本概念

代码示例分析

🍃深拷贝

基本概念

 代码示例分析

 

总结


 

引言

在C++中,对象的复制是一个非常重要的概念,它涉及到资源管理和内存安全。当一个对象被复制时,根据对象内部数据成员的复制方式不同,可以分为浅拷贝(Shallow Copy)和深拷贝(Deep Copy)两种类型

理解这两种复制的区别对于避免程序中的潜在错误至关重要。

本文将详细剖析这两个概念,并通过示例代码加以说明。

 

🍃浅拷贝

基本概念

  • 浅拷贝是指在复制对象时,仅仅复制对象的所有非静态成员变量的值
  • 如果这些成员变量是基本数据类型,那么它们的值会被直接复制到新对象中;
  • 如果是指针或引用类型,则只会复制指针或引用本身,而不会复制指针指向的数据。这意味着两个对象将共享同一份数据。

 

代码示例分析

//浅拷贝
#include <iostream>
using namespace std;

class ShallowCopy {
private:
    int* data;
public:
    ShallowCopy(int d) : data(new int(d)) {} // 构造函数
    ~ShallowCopy() { delete data; } // 析构函数
    void setData(int d) { *data = d; }
    int getData() const { return *data; }

    // 默认复制构造函数(浅拷贝)
    ShallowCopy(const ShallowCopy& source) : data(source.data) {}
};

int main() {
    ShallowCopy obj1(10);
    ShallowCopy obj2 = obj1; // 使用默认复制构造函数

    cout << "obj1 data: " << obj1.getData() << endl;
    cout << "obj2 data: " << obj2.getData() << endl;

    obj1.setData(20); // 修改 obj1 的数据

    cout << "After modifying obj1" << endl;
    cout << "obj1 data: " << obj1.getData() << endl;
    cout << "obj2 data: " << obj2.getData() << endl; // obj2 数据也被修改了

    return 0;
}

分析:

在这个例子中,obj1obj2 都指向同一个整数。因此,当 obj1 的数据改变时,obj2 的数据也随之改变。这展示了浅拷贝的一个主要缺点:两个对象之间存在数据依赖,可能导致不可预见的行为。 

 

🍃深拷贝

基本概念

  • 深拷贝则是创建一个全新的对象,并且这个新对象与原对象完全独立
  • 对于每个指针成员,深拷贝会分配新的内存空间来存储一份完全相同的数据副本。这样,即使原始对象的数据发生变化,也不会影响到复制的对象。

 

 代码示例分析

//深拷贝
#include <iostream>
using namespace std;

class DeepCopy {
private:
    int *data;
public:
    DeepCopy(int d) : data(new int(d)) {} // 构造函数
    ~DeepCopy() { delete data; } // 析构函数
    void setData(int d) { *data = d; }
    int getData() const { return *data; }

    // 自定义复制构造函数(深拷贝)
    DeepCopy(const DeepCopy &source) : data(new int(*source.data)) {}
};

int main() {
    DeepCopy obj1(10);
    DeepCopy obj2 = obj1; // 使用自定义复制构造函数

    cout << "obj1 data: " << obj1.getData() << endl;
    cout << "obj2 data: " << obj2.getData() << endl;

    obj1.setData(20); // 修改 obj1 的数据

    cout << "After modifying obj1" << endl;
    cout << "obj1 data: " << obj1.getData() << endl;
    cout << "obj2 data: " << obj2.getData() << endl; // obj2 数据没有变化

    return 0;
}

 

分析:

这里,obj2 是通过深拷贝从 obj1 创建的。因此,obj1obj2 各自拥有独立的数据副本。当 obj1 的数据被修改后,obj2 的数据保持不变,体现了深拷贝的优势——对象之间的数据独立性。

 

总结

  • 浅拷贝:简单复制成员变量的值,对于指针成员变量,只是复制指针值,两个对象共享同一块内存。快速简单,但在处理动态分配的资源时可能会导致数据不一致或内存泄漏等问题
  • 深拷贝:为成员变量分配新的内存空间,并复制原对象的成员变量的值到新对象的对应成员变量中,两个对象拥有独立的内存空间。虽然需要更多的系统资源和时间来完成复制过程,但它能确保两个对象之间的完全独立,避免了共享数据带来的风险

 

了解并正确使用浅拷贝与深拷贝,对于避免资源泄漏、数据损坏和潜在的内存管理错误至关重要。选择使用浅拷贝还是深拷贝取决于具体的应用场景。如果对象间不需要完全独立,且性能是关键考虑因素,可以选择浅拷贝。反之,若对象间必须保持独立,尤其是当对象包含动态分配的资源时,应使用深拷贝。

 

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/890727.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

数据中心物理安全的历史和演变

在当今的数字时代&#xff0c;数据中心托管已成为我们互联世界的支柱。这些设施在存储、管理和处理我们日常生活所需的大量信息方面发挥着至关重要的作用。从社交媒体平台和电子商务网站到流媒体服务和云计算&#xff0c;数据中心为我们依赖的数字服务提供支持。 随着企业越来…

2024.10.10计算机外部设备及调试培训

授课老师&#xff1a;杨戬 1.计算机组成 cpu&#xff0c;主板&#xff0c;内存&#xff0c;硬盘&#xff0c;电源&#xff0c;显示器&#xff0c;键盘和鼠标&#xff0c;光驱和显卡&#xff0c;其他外部设备。 2.虚拟机专业版转换 由于我们在2024.10.8的培训中已经安装了wi…

Spring Boot知识管理系统:安全与合规性

4系统概要设计 4.1概述 本系统采用B/S结构(Browser/Server,浏览器/服务器结构)和基于Web服务两种模式&#xff0c;是一个适用于Internet环境下的模型结构。只要用户能连上Internet,便可以在任何时间、任何地点使用。系统工作原理图如图4-1所示&#xff1a; 图4-1系统工作原理…

学习threejs,THREE.LineDashedMaterial 虚线材质,基于gosper高斯帕曲线生成雪花动画

&#x1f468;‍⚕️ 主页&#xff1a; gis分享者 &#x1f468;‍⚕️ 感谢各位大佬 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍⚕️ 收录于专栏&#xff1a;threejs gis工程师 文章目录 一、&#x1f340;前言1.1 ☘️THREE.LineDashedMaterial虚…

【ROS2实操四】参数服务

概念 在机器人系统中不同的功能模块可能会使用到一些相同的数据&#xff0c;比如&#xff1a; 导航实现时&#xff0c;会进行路径规划&#xff0c;路径规划主要包含&#xff0c; 全局路径规划和本地路径规划&#xff0c;所谓全局路径规划就是设计一个从出发点到目标点的大致路径…

iOS--NSURLSession Alamofire流程源码解析(万字详解版)

一、NSURLSession NSURLSession的主要功能是发起网络请求获取网络数据&#xff0c;是Apple的网络请求原生库之一。Alamofire就是对NSURLSession的封装&#xff0c;如果对NSURLSession不熟悉的话&#xff0c;那么Alamofire源码看起来会比较费劲的。因此我们先简单学习下NSURLSe…

Springboot整合抖音小程序获取access-token图片检测V3

抽取配置文件 appId以及secret需要自行在抖音开放平台获取 dy:appId: ttb0xxxxxsecret: 12a19a426xxxxxxxxxxxxx获取access-token 参照文档我们调用此接口需要先获取access-token 获取access-token官方文档地址 注意事项 client_token 的有效时间为 2 个小时&#xff0c;重复获…

力扣- 背包问题

关于背包问题,推荐卡哥的视频,结合代码随想录食用,效果绝佳!!! 传送门: 带你学透0-1背包问题&#xff01;| 关于背包问题&#xff0c;你不清楚的地方&#xff0c;这里都讲了&#xff01;| 动态规划经典问题 | 数据结构与算法_哔哩哔哩_bilibili 带你学透01背包问题&#xff…

HyperWorks汽车B-柱网格变形

在这一节&#xff0c;将练习如何使用变形域&#xff0c;实现汽车 B-柱有限元模型的网格变形。 图 7-13 网格变形前后的 B 柱模型 Step01&#xff1a;读取并查看模型。 打开模型文件 Exercise_7c.hm。 Step02&#xff1a;创建变形域。 (1) 通过路径 HyperMorph > Morph…

C++笔记之原子操作

C++笔记之原子操作 code review! 文章目录 C++笔记之原子操作1.初始化2.赋值3.取值4.赋给另一个原子类型5.`exchange`6.`compare_exchange_weak` 和 `compare_exchange_strong`使用场景7.注意事项在 C++ 中,原子类型提供了对共享变量的无锁操作,确保多线程环境下的安全。以下…

【Linux】为什么创建目录文件,硬链接数是2;创建普通文件时,硬链接数是1?(超详细图文解答)

前言 大家好吖&#xff0c;欢迎来到 YY 滴Linux系列 &#xff0c;热烈欢迎&#xff01; 本章主要内容面向接触过C的老铁 主要内容含&#xff1a; 欢迎订阅 YY滴C专栏&#xff01;更多干货持续更新&#xff01;以下是传送门&#xff01; YY的《C》专栏YY的《C11》专栏YY的《Lin…

图示详解OpenEuler下Samba多用户身份验证配置、测试

前言 前文《图例详解OpenEuler下Samba安装、配置和测试》已对Samba服务的工作原理、安装、配置和测试&#xff0c;做了系统的介绍&#xff0c;并对匿名用户的访问samba服务器做了配置&#xff0c;相必读者已对samba服务的流程有了初步、系统的了解&#xff0c;本文在以上基础上…

DevExpress WinForms中文教程:Data Grid - 如何完成数据输入验证?

本教程介绍DevExpress WinForm的Data Grid控件是如何利用网格组件完成数据输入验证的。 P.S&#xff1a;DevExpress WinForms拥有180组件和UI库&#xff0c;能为Windows Forms平台创建具有影响力的业务解决方案。DevExpress WinForms能完美构建流畅、美观且易于使用的应用程序…

vim 操作

vim编辑器的有三种工作模式&#xff1a;命令模式、插入模式和底行命令模式 打开进入命令模式&#xff1a; 由命令模式到输入模式&#xff1a;i:在光标前插&#xff1b;a:在光标后插&#xff1b;o:在下一行插 由输入模式进入命令模式&#xff1a;esc 由命令模式进入底行命令…

LabVIEW技术难度最大的程序

在LabVIEW开发中&#xff0c;技术难度最大的程序通常涉及复杂的系统架构、高精度的控制要求、大量数据处理&#xff0c;以及跨平台或多硬件设备的集成。以下是几类具有高技术难度的LabVIEW程序&#xff1a; 1. 高精度实时控制系统 LabVIEW中涉及高精度实时控制的系统程序&…

探索极致性能:R9-9950X与I9-14900K的深度较量

处理器是电脑及服务器的心脏&#xff0c;处理器的性能直接影响着电脑或服务器的运行效率、多任务处理能力以及整体用户体验。一款优秀的处理器&#xff0c;能够确保系统流畅运行&#xff0c;无论是处理复杂的数据分析、高强度的图形渲染&#xff0c;还是享受沉浸式的游戏体验&a…

【spring ai】java 实现RAG检索增强,超快速入门

rag 需求产生的背景介绍&#xff1a; 在使用大模型时&#xff0c;一个常见的问题是模型会产生幻觉&#xff08;即生成的内容与事实不符&#xff09;&#xff0c;同时由于缺乏企业内部数据的支持&#xff0c;导致其回答往往不够精准和具体&#xff0c;偏向于泛泛而谈。这些问题…

Selenium实现滑动滑块验证码验证!

背景&#xff1a;在部分的登录中有滑动验证码的验证&#xff0c;由于滑动验证码的缺块是随机的就导致实现起来比较困难&#xff01; 01、实现方案 模板匹配 通过openCV分析两个图片的相似度&#xff0c;获取两个相似度很高图片的坐标&#xff0c;从而计算两个图片的距离。 轮…

基础sql

在执行删除操作之前&#xff0c;建议先运行一个 SELECT 查询来确认你要删除的记录。这可以帮助你避免误删数据。 删除字段id默认值为空字符串的所有数据 delete from users where id ; 删除字段id默认值为null的所有数据 delete from users where id is null; 删除字段upd…

数据容器(序列)的切片

1.数据容器&#xff1a;列表&#xff0c;元组&#xff0c;字符串 2..切片可以提取序列中的片段或整个序列 ##切片的格式为&#xff1a;变量名[ 起始位置:停止位置&#xff1a;步数] #起始位置为序列首位时可省略不写&#xff0c;停止位置为序列尾部时也如此&#xff0c;##停止…