首页 > 编程语言 >C++逆向分析——对象拷贝

C++逆向分析——对象拷贝

时间:2023-04-09 11:13:19浏览次数:48  
标签:逆向 对象 C++ 运算符 复制 拷贝 赋值 构造函数

对象拷贝

我们通常存储对象,都用数组、列表之类的来存储,那如下所示我们使用数组来存储对象,但是在工作中发现这个数组不够用了,就需要一个更大的数据,但我们重新创建一个数组还需要把原来的数据复制过来;在C语言中可以使用函数来进行拷贝,直接拷贝内存,在C++中实际上跟C语言要做的事情是一样的,在C++中就称之为对象拷贝

images/download/attachments/12714553/image2021-4-17_18-50-20.png

拷贝构造函数

如何在C++中拷贝构造函数,来看一下如下代码:

images/download/attachments/12714553/image2021-4-17_19-1-10.png

可以看见我们定义了一个类,然后创建了两个对象obj、objNew,但是第二个对象的语法很奇怪,传入的参数是第一对象,其实这就是默认拷贝析构函数。

其本质就是很简单的内存复制:

images/download/attachments/12714553/image2021-4-17_20-4-58.png

上面的内存复制是在栈中,而我们想在堆中去拷贝可以这样写:

CObject* p = new CObject(obj);

如上所示,我们是通过拷贝析构函数在内存中创建了一个新的对象,而如果该类本身有一个父类,父类会被拷贝吗?我们写一段代码来论证一下:

images/download/attachments/12714553/image2021-4-17_22-28-37.png

那么这段代码,拷贝构造函数不仅可以将当前对象的内容复制,还可以将父类的内容复制过来。

拷贝构造函数是编译器已经提供的,其已经非常成熟了,通常情况下是不建议自己写拷贝构造函数的,除非出现类中包含指针类型的成员,这种情况是需要自己重些拷贝构造函数的,因为拷贝构造函数只是会拷贝当前指针成员的值,并不会拷贝指针成员指向的内容。

所以这种拷贝方式,我们可以称之为浅拷贝;而如果可以做到能够复制成员的情况下,还可以将指针指向的内存地址复制过来,并自动申请一块新的内存提供,这种方式我们称之为深拷贝

如果要实现深拷贝,我们就需要自己重写拷贝构造函数。

MyObject(const MyObject& obj) { m_nLength = obj.m_nLength; m_strBuffer = new char[m_nLength]; memset(m_strBuffer, 0, m_nLength); strcpy(m_strBuffer, obj.m_strBuffer); }

images/download/attachments/12714553/image2021-4-17_23-48-7.png

需要注意的是这个格式是固定的,不要自己「自由发挥」。

总结:

  1. 如果不需要深拷贝,就不要自己添加拷贝构造函数;

  2. 如果你天假了拷贝构造函数,那么编译器将不再提供,所有的事情都需要由新添加的函数自己来处理。

重载赋值运算符

上一章学习了如何通过拷贝对象函数的方式来实现对象拷贝,这里就来学习使用重载赋值运算符实现对象拷贝。

在C++中是允许我们在两个对象之间直接使用赋值运算符的:

CObject a(1, 2), b(3, 4); b = a;

images/download/attachments/12714553/image2021-4-18_16-26-21.png

那么赋值运算符实现的对象复制是否会当前复制对象继承的父类进行复制呢?

images/download/attachments/12714553/image2021-4-18_16-36-55.png

如上图所示,赋值运算符是可以复制父类的。

但是在这里赋值运算符是否就非常完美了呢?不是的,赋值运算符和拷贝构造函数是有相同缺点的,那就是其默认都是浅拷贝

我们想要解决这个问题就需要重写一个赋值运算符,自己来实现深拷贝

images/download/attachments/12714553/image2021-4-18_21-45-51.png

标签:逆向,对象,C++,运算符,复制,拷贝,赋值,构造函数
From: https://www.cnblogs.com/bonelee/p/17300008.html

相关文章

  • C++逆向分析——友元、内部类、命名空间和static
    友元友元可以理解为:朋友、元素;老师认为这个友元是C++中的一个垃圾,因为友元的存在破坏了面向对象的封装性,不推荐使用,之所以有这个章节是因为有人不了解这个概念。注意:在一些新版本的C++编译器里面已经不再提供类似于友元这样的特性了。大家都知道在C++中对象的私有成员,外部是无......
  • C++逆向分析——运算符重载
    运算符重载现在有一个类,其中有一个函数用于比较2个类的成员大小:#include<stdio.h> classNumber{private:intx;inty;public:Number(intx,inty){this->x=x;this->y=y;}intMax(Number&n){returnthis->x>n.x&&this->y>n.......
  • C++逆向分析——模版
    模版假设有一个冒泡排序的函数:voidSort(int*arr,intnLength){inti,k;for(i=0;i<nLength;i++){for(k=0;k<nLength-1-i;k++){if(arr[k]>arr[k+1]){inttemp=arr[k];arr[k]=arr[k+1];arr[k+1]=temp;}}}}但是这个冒泡......
  • C++逆向分析——构造函数和析构函数
    构造函数与析构函数构造函数structStudent{inta;intb; Student(){printf("Look.");} voidInit(inta,intb){this->a=a;this->b=b;} };如上代码中,我们发现了存在一个函数,这个函数没有返回类型并且与结构体名称一样,那这段函数在什么......
  • Code-C++ Invoke Python
    Code-C++InvokePythonhttps://www.cnblogs.com/yongchao/p/17299892.html使用C或C++扩展Python扩展和嵌入Python解释器Python3.10.11Python/CAPI参考手册Python3.11.3Python/CAPI参考手册https://www.cnblogs.com/lidabo/p/17043302.htmlhttps://bl......
  • C++逆向分析——继承
    继承structPerson{intage;intsex;}; structTeacher{intage;intsex;intlevel;intclassId;};如上代码中可以看见,Teacher类与Person类都存在着相同的2个成员age和sex,那么这就相当于重复编写了,我们可以通过继承的方式避免这样重复的编写(当前类名称:......
  • C++逆向分析——new和delete new[]和delete[]
    在堆中创建对象我们可以在什么地方创建对象?全局变量区,在函数外面在栈中创建对象,也就是函数内在堆中创建对象注意:之前一直提到的堆栈实际上是两个概念->堆、栈,我们之前所讲的就是栈,从本章开始要严格区分。在C语言中,我们可以通过一个函数去申请一块内存,就是malloc(N)......
  • C++逆向分析——类成员的访问控制
    类成员的访问控制课外→好的编程习惯:定义与实现分开写,提升代码可读性。如下代码,Student这个类的所有成员我们都可以调用,但是我们不想让被人调用Print1这个方法该怎么?structStudent{intage;intsex; voidPrint1(){printf("FuncPrint1");} voidPrint......
  • C++逆向分析——引用
    引用类型引用类型就是变量的别名,其在初始化时必须要赋值。//基本类型intx=1;int&ref=x;ref=2;printf("%d\n",ref); //类Personp;Person&ref=p;ref.x=10;printf("%d\n",p.x); //指针类型int******x=(int******)1;int******&ref=x;r......
  • C++逆向分析——继承与封装
    面向对象程序设计之继承与封装之前已经学习过继承和封装了,但是要在实际开发中使用,光学语法和原理是不够的,在设计层面我们需要做一些优化。如下代码是继承的例子:#include<stdio.h> classPerson{public:intAge;intSex; voidWork(){printf("Person:Work()......