C++—浅拷贝、深拷贝、写时拷贝讲解(附代码)

对于普通的类型来说,拷贝没什么大不了的。

int a = 0;int b = a;

不会出现任何问题。

而类对象与普通对象不同,类对象内部结构一般较为复杂,存在各种成员变量。

浅拷贝

首先来说说我们常遇到的浅拷贝的情况。

#include  class student{public:    student()      // 构造函数,p指向堆中分配的一空间    {        _name = new char(100);        printf("默认构造函数\n");    }    ~student()     // 析构函数,释放动态分配的空间    {        if (_name != NULL)        {            delete _name;            _name = NULL;            printf("析构函数\n");        }    }private:    char * _name;     // 一指针成员};int main(){    student a;    student b(a);   // 复制对象    return 0;}

这段代码乍看之下没什么毛病,通过类的默认构造函数将 a 复制给 b ,但是一旦运行就会程序崩溃
经过我的刻苦学习与钻研,终于发现其中的问题所在。
由于我的类没有拷贝构造函数,所以student b(a)会调用,编译器自动生成的一个默认拷贝构造函数,该构造函数完成对象之间的位拷贝。位拷贝又称浅拷贝
浅拷贝

浅拷贝只是拷贝了指针,并没有创建新的空间,使得两个指针指向同一个地址,这样在对象块结束,调用函数析构的时,会造成同一份资源析构2次,即delete同一块内存2次,造成程序崩溃。

立即学习“C++免费学习笔记(深入)”;

浅拷贝使得 a 和 b 指向同一块内存,任何一方的变动都会影响到另一方。

由于 a 和 b 指向的是同一块内存空间,当 a 释放了后,b 指向的内存空间不复存在,所以会出现内存泄露的情况。

如何避免浅拷贝害人呢?
养成自定义拷贝构造函数的习惯,当显式定义了拷贝构造函数后,编译器就会调用拷贝构造函数了,为了不出现程序崩溃,请使用自定义拷贝构造函数,当然我们自己如果把代码写成了浅拷贝的形式,那也不是不可能的事。

深拷贝

// 使用自定制拷贝构造函数,完成深拷贝!!!class A{public:    A()      // 构造函数,p指向堆中分配的一空间    {        m_pdata = new char(100);        printf("默认构造函数\n");    }    A(const A& r)    // 拷贝构造函数    {        m_pdata = new char(100);    // 为新对象重新动态分配空间        memcpy(m_pdata, r.m_pdata, strlen(r.m_pdata));        printf("copy构造函数\n");    }    ~A()     // 析构函数,释放动态分配的空间    {        if (m_pdata != NULL)        {            delete m_pdata;            printf("析构函数\n");        }    }private:    char *m_pdata;     // 一指针成员};int main(){    A a;    A b(a);   // 复制对象    return 0;}

在拷贝构造函数中,为 b 对象 new 了一个新的空间,这样 a 和 b 指向的是不同的空间,只是内容一致,但是互不影响。
重复的去开辟空间和释放空间效率是很低的,聪明的地球人决定使用写时拷贝。

写时拷贝

写时拷贝:引入一个计数器,每片不同内容的空间上都再由一个计数器组成,在构造第一个类指向时,计数器初始化为1,之后每次有新的类也指向同一片空间时,计数器加 1 ;在析构时判断该片空间对应计数器是否为1,为1则执行清理工作,大于1则计数器减 1 。如果有需要进行增删等操作时,再拷贝空间完成,有利于提高效率。

class String{public:    String(const char* str = "")        :_str(new char[strlen(str) + 1 + 4])//+1表示字符串后面要放一个'\0',+4表示多开辟一个空间存放引用计数    {        _str += 4;//_str指向数据存放区        strcpy(_str, str);        _GetCount() = 1;    }    String(const String& s)        :_str(s._str)    {        _GetCount()++;    }    String& operator=(String& s)    {        if (this != &s)        {            if (--_GetCount() == 0)            {                delete[](_str - 4);            }            ++s._GetCount();            _str = s._str;        }        return *this;    }    ~String()    {        if (--_GetCount() == 0)        {            delete[](_str - 4); // 注意:由于计数器存放在了_str首地址-4的地址上,所以在析构时一定要注意全部释放,避免内存泄漏。        }    }public:    int& _GetCount()    {        return *((int*)_str - 1);    }private:    char* _str;};

相关文章:

C#浅拷贝和深拷贝实例解析

Python中的赋值、浅拷贝、深拷贝介绍        

以上就是C++—浅拷贝、深拷贝、写时拷贝讲解(附代码)的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1432833.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2025年12月17日 08:39:18
下一篇 2025年12月13日 03:06:55

相关推荐

  • Golang如何实现深拷贝 值类型与指针类型区别

    深拷贝需创建完全独立的副本,避免原对象被修改。Go中通过手动复制、Gob序列化或第三方库实现,注意循环引用、不可导出字段及性能开销,选择方法需权衡控制粒度、通用性与便捷性。 在Go语言中,深拷贝是指创建一个新对象,其字段值与原对象完全相同,并且所有嵌套的引用类型(如指针、切片、map等)也都是独立的…

    2025年12月15日
    000
  • Golang反射深拷贝实现 递归处理复杂类型

    答案:Go语言通过反射实现深拷贝,核心是使用reflect递归复制结构体、切片、映射和指针类型,确保副本独立。1. 根据Kind判断类型;2. 结构体遍历字段复制;3. 切片和映射创建新对象并递归元素;4. 指针处理层级与nil;5. 防止共享数据和循环引用。 在 Go 语言中,标准库不提供深拷贝功…

    2025年12月15日
    000
  • Python怎么深度拷贝一个对象_Python深拷贝与浅拷贝详解

    深度拷贝能创建完全独立的对象副本,修改副本不影响原对象,适用于嵌套结构或复杂对象的复制。 深拷贝,简单来说,就是完完全全复制一份,跟原来的对象再无瓜葛。修改拷贝后的对象,不会影响到原始对象。 Python实现深度拷贝,主要靠 copy 模块里的 deepcopy() 函数。 copy.deepcop…

    2025年12月14日
    000
  • python中如何深度拷贝一个对象_Python深拷贝与浅拷贝的区别与实现

    深度拷贝通过copy.deepcopy()递归复制对象及其所有嵌套对象,确保新旧对象完全独立;浅拷贝通过copy.copy()或切片仅复制对象本身和直接引用,共享嵌套的可变对象。选择深拷贝可避免修改副本影响原始数据,尤其在处理复杂结构、循环引用或需数据隔离时至关重要;浅拷贝适用于性能敏感且无需修改嵌…

    2025年12月14日
    000
  • Python中的深拷贝与浅拷贝有什么区别?

    深拷贝和浅拷贝的核心区别在于对嵌套对象的处理:浅拷贝仅复制对象顶层结构,共享嵌套对象引用,修改嵌套内容会影响原对象;深拷贝则递归复制所有层级对象,创建完全独立的副本,互不影响。Python中通过copy.copy()实现浅拷贝,适用于不可变嵌套或需共享数据的场景;copy.deepcopy()实现深…

    2025年12月14日
    000
  • Python 中的浅拷贝与深拷贝:区别与应用场景

    浅拷贝创建新容器但共享内部元素,深拷贝递归复制所有层级确保完全独立。Python中通过切片、copy()实现浅拷贝,copy.deepcopy()实现深拷贝,前者高效但修改嵌套可变元素会影响原对象,后者开销大但隔离彻底。 Python中的浅拷贝与深拷贝,核心在于它们处理复合对象内部元素的方式不同。简…

    2025年12月14日
    000
  • java Arrays.copyOf实现浅拷贝

    Arrays.copyOf实现浅拷贝,复制基本类型数组时值独立,复制引用类型数组时共享对象引用,修改对象会影响原数组和副本,需手动实现深拷贝以获得完全独立的副本。 Java 中 Arrays.copyOf 方法实现的是浅拷贝,这意味着它只复制数组本身,而不递归复制数组中对象的副本。对于基本数据类型,…

    2025年12月2日 java
    000
  • js怎样实现深拷贝

    深拷贝是指创建一个与原对象完全独立的新对象,修改新对象不会影响原对象。1. 实现深拷贝的方法有多种,最简单的是json.parse(json.stringify(obj)),但其无法处理函数、undefined、symbol及循环引用。2. 更可靠的深拷贝需使用递归配合weakmap缓存已拷贝对象,…

    2025年11月30日 web前端
    000
  • 在Java中如何实现对象的深拷贝工具方法_深拷贝实践指南

    答案:Java中深拷贝确保对象完全独立,避免数据污染。通过序列化可实现通用深拷贝,要求对象及成员均实现Serializable接口;JSON序列化(如Gson)无需实现Serializable,但需无参构造函数;手动重写clone()方法效率高但维护成本大。选择策略需根据性能需求、类结构和依赖环境,…

    2025年11月28日 java
    000
  • JavaScript中如何实现深拷贝函数以处理循环引用?

    深拷贝通过创建完全独立的对象避免修改原对象,使用递归结合WeakMap可处理循环引用;为防堆栈溢出,可用循环替代递归;根据场景选择JSON方法、递归、循环或第三方库以平衡性能与功能。 深拷贝的核心在于创建一个与原始对象完全独立的新对象,这意味着修改新对象不会影响到原始对象。处理循环引用则需要在拷贝过…

    2025年11月25日 web前端
    000
  • js怎么实现原型链的深拷贝

    javascript中实现原型链的深拷贝,核心在于创建一个与原对象具有相同原型但属性完全独立的新对象,并递归复制所有自身可枚举属性,同时处理循环引用和特殊类型。1. 对于基本类型、null、undefined、symbol和函数,直接返回原值或引用;2. 使用weakmap记录已处理对象,防止循环引…

    2025年11月25日 web前端
    000
  • JS如何实现深拷贝

    js实现深拷贝的核心答案是通过递归复制对象所有层级并切断引用关系,以确保副本与原数据完全独立。最简单的方法是使用json.parse(json.stringify(obj)),适用于仅含基本类型和普通对象的“纯净”数据,但会丢失函数、undefined、symbol等,且无法处理循环引用;更通用的方…

    2025年11月5日 web前端
    000
  • JS中的深拷贝和浅拷贝有什么区别?

    浅拷贝和深拷贝的核心区别在于是否创建原对象的完整独立副本。1. 浅拷贝仅复制对象第一层属性,若属性为引用类型则复制其地址,常见方法包括object.assign、扩展运算符和数组的slice()、concat(),修改嵌套对象会影响原对象;2. 深拷贝递归复制所有层级,生成完全独立对象,常用方法有j…

    2025年11月4日 web前端
    000
  • JS如何实现浅拷贝

    js浅拷贝是指只复制对象或数组的第一层属性或元素,若属性或元素为对象或数组,则复制其引用而非新对象。1. 使用object.assign()可将源对象属性复制到新对象,但嵌套对象仍共享引用;2. 使用展开运算符(…)实现对象浅拷贝,效果与object.assign()相同;3. 手动遍历…

    2025年11月3日 web前端
    000
  • clone方法在Java中如何实现深拷贝

    通过重写clone方法并递归复制引用类型可实现深拷贝:1. 类需实现Cloneable接口;2. 重写public的clone()方法;3. 对引用字段调用其clone()或新建副本;4. 集合中为可变对象时需遍历克隆每个元素,确保副本完全独立。 在 Java 中,clone 方法本身不会自动实现深…

    2025年11月1日
    200

发表回复

登录后才能评论
关注微信