【C++】详解深浅拷贝的概念及其区别

举报
修修修也 发表于 2024/09/30 17:03:02 2024/09/30
【摘要】 🦄个人主页:修修修也 🎏所属专栏:C++ ⚙️操作环境:Visual Studio 2022​编辑目录什么是拷 贝 什么是浅拷 贝 什么是深拷 贝 深浅拷 贝 的区 别 及适用 场 景 写 时 拷 贝 结语 什么是拷贝        在C++编程中,拷贝是一个非常重要的概念,对于理解和使用类和对象起着至关重要的作用。        当定义一个类时,我们显式地或隐式地指定在此类型的对象拷贝...

🦄个人主:修修修也

🎏所属专栏:C++

⚙️操作:Visual Studio 2022

​编辑


什么是拷

什么是浅拷

什么是深拷

深浅拷 的区 及适用

结语


什么是拷

        在C++编程中,是一个非常重要的概念,对于理解和使用类和对象起着至关重要的作用。

        当定义一个类时,我们地或地指定在此类型的对象赋值销毁时做什么。一个类通过定义五种特殊的成员函数来控制这些操作,包括:构造函数( copy constructor)、拷贝赋值运算符( copy-assignment operator )、移构造函数( moveconstructor)、移动赋值运算符(move-assignment operator)析构函数( destructor)

        拷和移构造函数定义了当用同型的另一个象初始化本做什么和移动赋值运算符定义了将一个予同型的另一个做什么。析构函数定义了当此类型对象销毁时做什么。我们称这些操作为拷贝控制操作(copy control)。

        如果一个类没有定所有这些拷贝控制操作,编译器会动为它定缺失的操作。因此,很多类会忽略这些拷贝控制操作。但是,对一些类来说,依赖这些操作的默认定义会导致灾难 ! 通常,实现拷贝控制操作最困难的地方是首先认识到什么时候需要定义这些操作。
在定义任何C++类时,拷贝控制操作都是必要部分。

        简单来讲就是,基于面向对象语言对类的使用,我们自然的衍生出了需要将某个类对值给另一类对/用一个已存在的象去初始化另一个正在声明的的情况,如:

class Date

{

public:

    //类函数声明or定义部分




    //成员变量

private:

    int _year;

    int _month;

    int _day;

};




int main()

{

    Date d1;

    Date d2 = d1;

Date d3(d1);




    return 0;

}

        这时我们就需要将存在的象的内容"拷"需要的地方,如下图:​编辑


什么是浅拷

        清楚了什么是拷贝后,我们来讲一下什么是浅拷.

        浅拷贝是指将一个对象的值赋给另一个对象时,只是简单地将象的每个成员变量的值进行复制。这意味着两个象的内容是完全一模一,即:

​编辑

        浅拷贝看似没有什么问题,但当我们面对含有指针类型成员变的类时,浅拷贝就会出现一些严重的事故,浅拷使两个类对象共享相同的内存地址,当一个象的值发生改变时,另一个象的也会相地改这种拷贝方式在某些情况下可能会带来一些意想不到的问题,特别是当涉及到动态内存分配时,如:

class Stack

{

public:

    //类函数声明/定义部分




    //成员变量

private:

    int* arr;

    int top;

    int capacity;

};

        对于栈类,它有三个成员变量,一个是指向存储栈内数据位置的指针,还有两个是整型,当我们创建了一个类对象st1时,内存中的逻辑关系如下图:​编辑

        然而,当我们使用浅拷st1拷贝给st2,会出现这样的情况:

​编辑

        从图中可以看出,浅拷贝后的st2中的内容是和st1一模一样的,连都指向同一,这样两个类对象共享相同的内存地址,当一个象的值发生改变时,另一个象的也会相地改并且如果类对象中指向的这块空间原本是动态开辟的,那么当其中一个类对象析构这块间释,另一个类对象中存个指就是一个空指,极容易造成非法访问问题,即便是不使用,也不能销毁,否也会造成内存空二次放的问题.


什么是深拷

        深拷贝是一种比较安全和稳定的对象拷贝方式,它在拷贝时如果遇到指针类型的数据,不会像浅拷贝那样单纯的只赋值指针的位置,而是会重新动态开辟一新的空,然后将原指指向空的内容拷到自己新开辟的空,这样,原始象和拷贝对象会有各自独立的内存空,互不影响

        深拷贝可以避免因为对象指向同一块内存而导致的潜在问题,如对象析构时可能引发的内存泄漏针悬等情况。

        深拷贝图示如下:

​编辑


深浅拷的区及适用

        简单来说,浅拷贝就是单纯的一模一复制类对象的内容,而深拷贝是对类对象的内容行深次的拷

        用阿拉丁神灯的故事给大家打个比方吧:
​编辑

        浅拷的结果是这样的:

​编辑

        而深拷的结果是这样的:

​编辑

        通过前文我们对浅拷贝和深拷贝的了解,其实不难分析出,浅拷的适用场景是当类中不含有指针类型的成员变量的成时(注意,类中如果包含其他类作为成员时,成员类也同样不应含有指针类型成员),在这种场景下使用浅拷贝就非常快捷且方便,不会有什么问题.

        而对于中包含指针类型的成员变,特别是这个指针指向的是某块动态开辟的内存空间时,拷贝就使用深拷实现,否则就会出现之前提到的指针悬空或内存泄漏等问题.


        写入时复制是一种计算机程序设计领域的优化策略。其核心思想是,如果有多个调用者同时请求相同资源(如内存或磁盘上的数据存储),他们会共同获取相同的指针指向相同的资源,直到某个调用者试图修改资源的内容时,系统才会真正复制一份专用副本(private copy)给该调用者,而其他调用者所见到的最初的资源仍然保持不变。这个过程对其他的调用者是透明的(transparently)。此作法的主要优点是如果调用者没有修改该资源,就不会有副本(private copy)被建立,因此多个调用者只是读取操作是可以共享同一份资源。

        写时拷贝详解文章:

【Linux】写 复制( CopyOnWrite)|写 |rcu


结语

希望篇关于 深浅拷 的博客能大家有所帮助,迎大佬留言或私信与我交流.

学海漫浩浩,我亦苦作舟!关注我,大家一起学,一起!

相关文章推荐

【C++】 动态 内存管理

【C++】 库类 string

【C++】构建第一个C++ :Date

【C++】 的六大默 函数及其特性 (万字 )

【C++】内 函数

【C++】函数重

【C++】什么是 ?

【C++】缺省参数(默 参数 )

【C++】命名空


​编辑

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。