C++深复制和浅复制讲解

 更新时间:2022年03月10日 16:45:38   作者:机器学习入坑者  
这篇文章主要介绍了C++深复制和浅复制讲解,C++中深复制和浅复制最大的区别在“类包含指针类型的数据成员”时,下面感兴趣的小伙伴和小编一起进入文章了解更多相关内容吧

前言:

深复制和浅复制在python中同样存在,但是由于python中没有指针这个概念,所以当时学python时理解这个问题非常困难。实际上,通过这些天的学习,越发的认为C++的语法虽然复杂,但是由于其每个概念都比较清晰反而比python更好理解。python中很多语法都有些“模糊”,尤其是它的魔法函数部分,使用的时候总是怕自己理解错误从而造成误用。

1、什么是浅复制

在C++中深复制和浅复制最大的区别在“类包含指针类型的数据成员”时。由于默认的复制构造函数完成的是对象成员的数值复制,当原对象含有指针P指向地址xxx时,通过原对象复制得到的新对象的指针P同样指向地址xxx,造成同一个地址xxx被两个对象同时指向,这是非常不安全的,因为任一对象对地址xxx的操作很可能会对另一个对象造成不良影响。下面定义的Duck类就包含指针成员foot,该成员指向数组的首地址:

class Duck {
public:
    Duck() { foot = new int[2](); }
    int *foot;
};

首先定义一个duck对象,然后通过duck复制得到anotherDuck,那么二者的指针成员foot指向相同的地址。anotherDuck对指针成员foot指向的内存进行操作,和duck的指针成员foot对指向的内存进行操作是等价的,因为两个对象的foot指针都指向相同的地址,这就是不安全的来源:

Duck duck;
Duck anotherDuck = duck;
/// anotherDuck对foot指向内存进行赋值
anotherDuck.foot[1] = 666;

此外,为了证明原对象和新对象的foot指针都指向相同的地址,可以查看一下:

printf("their id is %p and %p \n", duck.foot, anotherDuck.foot);
/// 得到的结果证明二者确实指向相同的地址
their id is 005B0CE8 and 005B0CE8

总之,上面的现象就是浅复制,这种浅复制很可能带来不安全因素,这种不安全同样体现在内存释放时(同一个内存不能释放两次),所以需要使用下面将要介绍的深复制。

2、如何实现深复制

按照掌握的资料,深复制需要编写赋值构造函数,创建成员指针所指向内存的新副本。比如上一节定义的Duck类指针成员foot,复制构造函数需要创建foot指向的内存的新副本:

Duck(Duck &duck) {
    /// 1、创建新的内存空间
    foot = new int[2]();
    /// 2、将原对象的指针所指向的数组数值
    /// 全部复制到新对象指针指向的数组
    for (int i = 0; i < 2; i++) {
        foot[i] = duck.foot[i];
    }
}

其中第1步目的是创建新的内存空间,让新对象的指针成员指向新的内存,而不是和原对象指向相同的内存,同时必须保证新的内存所存储的类型和原对象相同,都是int类型的2个元素的数组。第2步的目的是将原对象指针所指向的数组的值,全部复制到新对象指所针指向的数组中。经过上面的两个步骤,深度复制完成。

为了确保原对象duck和新对象anotherDuck的foot指针所指向的地址不同,可以进行下面的测试,输出两个foot指向的地址:

printf("their id is %p and %p \n", duck.foot, anotherDuck.foot);
/// 结果显示两个foot指向的地址是不同的
their id is 01250FA0 and 01250B40

到此这篇关于C++深复制和浅复制讲解的文章就介绍到这了,更多相关C++深复制和浅复制内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C++实现俄罗斯方块

    C++实现俄罗斯方块

    这篇文章主要为大家详细介绍了C++实现俄罗斯方块,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-01-01
  • C++数据结构之AVL树的实现

    C++数据结构之AVL树的实现

    AVL树是高度平衡的而二叉树,它的特点是AVL树中任何节点的两个子树的高度最大差别为1,本文主要给大家介绍了C++如何实现AVL树,需要的朋友可以参考下
    2022-06-06
  • C++ 中随机函数random函数的使用方法

    C++ 中随机函数random函数的使用方法

    这篇文章主要介绍了C++ 中随机函数random函数的使用方法的相关资料,希望通过本文能帮助到大家,需要的朋友可以参考下
    2017-09-09
  • c++连接mysql数据库的两种方法(ADO连接和mysql api连接)

    c++连接mysql数据库的两种方法(ADO连接和mysql api连接)

    现在正做一个接口,通过不同的连接字符串操作不同的数据库。要用到mysql数据库,C++连接mysql有2种方法:利用ADO连接、利用mysql自己的api函数进行连接,下面看看如何用吧
    2013-12-12
  • 全面解析C++中的new,operator new与placement new

    全面解析C++中的new,operator new与placement new

    以下是C++中的new,operator new与placement new进行了详细的说明介绍,需要的朋友可以过来参考下
    2013-09-09
  • 函数指针的强制类型转换实现代码

    函数指针的强制类型转换实现代码

    函数指针的强制类型转换实现代码。需要的朋友可以过来参考下,希望对大家有所帮助
    2013-10-10
  • C语言链表实现简易通讯录

    C语言链表实现简易通讯录

    这篇文章主要为大家详细介绍了C语言链表实现简易通讯录,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-05-05
  • C语言素数(质数)判断的3种方法举例

    C语言素数(质数)判断的3种方法举例

    这篇文章主要给大家介绍了关于C语言素数(质数)判断的3种方法,质数是只能被1或者自身整除的自然数(不包括1),称为质数,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2023-11-11
  • C语言实现线索二叉树的定义与遍历示例

    C语言实现线索二叉树的定义与遍历示例

    这篇文章主要介绍了C语言实现线索二叉树的定义与遍历,结合具体实例形式分析了基于C语言的线索二叉树定义及遍历操作相关实现技巧与注意事项,需要的朋友可以参考下
    2017-06-06
  • c++中的volatile和variant关键字详解

    c++中的volatile和variant关键字详解

    大家好,本篇文章主要讲的是c++中的volatile和variant关键字详解,感兴趣的同学赶快来看一看吧,对你有帮助的话记得收藏一下
    2022-01-01

最新评论