C++:拷贝构造函数与赋值的区别

news/2024/10/19 9:40:17/

目录

拷贝构造函数

拷贝构造函数的使用方法

拷贝构造函数与赋值运算符的区别

谈深拷贝和浅拷贝

浅拷贝

注意:

深拷贝


拷贝构造函数

拷贝构造函数的也是一种构造函数,它的作用是将一个类的成员拷贝到另一个类中,类似于赋值。拷贝构造函数分为深拷贝和浅拷贝。

先来定义一个拷贝构造函数(构造函数可以重载),看招:

#include<iostream>
using namespace std;
class date
{
public:date(int year=0, int month=0, int day=0){_year = year;_month = month;_day = day;}date(const date& d)//拷贝构造函数{this->_year = d._year;this->_month = d._month;this->_day = d._day;}void print(){cout << _year << "-" << _month << "-" << _day << endl;}
private:int _year;int _month;int _day;
};

 将一个类拷贝到另一个类中,自然是需要对应的参数的,参数就是类,这里可以传递指针,引用更好,只是传值形参的话,会造成无限递归。

拷贝构造函数的使用方法

拷贝构造函数的使用:
1.使用();2.使用'=';像这样

拷贝构造函数与赋值运算符的区别

那么拷贝构造函数和赋值运算符有什么区别呢,先来看一段代码对比一下:

int main()
{date d1(20244, 4, 24);date d2=d1;date d3;d3= d1;//编译器会自动将其转化为d3(d1);return 0;
}

这里d2采用的拷贝构造函数的方式,d3采用赋值的方式,通过观察,我们可以发现,前者是创造变量时就对类进行了赋值,这个赋值叫做初始化,而后者是先定义好的类,后续赋值,在赋值之前是已经将变量创建好的;

谈深拷贝和浅拷贝

先说浅拷贝

浅拷贝

浅拷贝就是对成员变量进行一一对应赋值,来看一个代码:

#include<iostream>
using namespace std;
class date
{
public:date(int a=1,int b=1){_a = a;_b = b;}date(const date& d){_a = d._a;//成员变量简单的赋值_b = d._b;}void print(){cout << _a << ',' << _b << endl;}~date(){cout << "~date" << endl;}
private:int _a;int _b;
};int main()
{date d1(2,5);date d2(d1);d2.print();return 0;
}

 在这个代码中,在对d2进行初始化的时候,是将d1的成员变量对d进行了赋值;最后代码结束存在两次析构,分别是d2和d1的;

注意:

对于简单的成员变量进行简单的复制操作并无大碍,但是如果是指针类型的变量就会出现问题;看代码;

#include<iostream>
using namespace std;
class date
{
public:date(int b=1){_a =new int[4];_b = b;}date(const date& d){_a = d._a;_b = d._b;}void print(){cout << _a << ',' << _b << endl;}~date(){free(_a);//拷贝后两个成员变量都指向同一块空间,会造成多次析构cout << "~date" << endl;}
private:int* _a;int _b;
};int main()
{date d1(5);date d2(d1);d2.print();return 0;
}

代码中_a为指针类型,初始化是对其进行开辟空间;代码结束对类进行析构,但是问题来了,浅拷贝只是简单的赋值,针对_a来说,d1和d2的_a都指向同一片空间,这就造成了在代码结束时,这片空间会释放两次,就会发生错误,对此就需要进行深拷贝来解决。 

深拷贝

#include<iostream>
using namespace std;
class date
{
public:date(int b=1){_a =new int[4];_a[0] = 10;_b = b;}date(const date& d){_a = new int[4];memcpy(_a, d._a, sizeof(int) * 4);//将d2的数据拷贝过来_b = d._b;}void print(){cout << _a[0] << ',' << _b << endl;}~date(){free(_a);cout << "~date" << endl;}
private:int* _a;int _b;
};int main()
{date d1(5);date d2(d1);d2.print();return 0;
}

在拷贝构造的时候对本类的_a也进行开辟空间,然后把另一类的数据利用memcpy拷贝过来就OK了。 这样就不会出现析构多次同一片空间的问题。


http://www.ppmy.cn/news/1443354.html

相关文章

Stable Diffusion教程:文生图

最近几天AI绘画没有什么大动作&#xff0c;正好有时间总结下Stable Diffusion的一些基础知识&#xff0c;今天就给大家再唠叨一下文生图这个功能&#xff0c;会详细说明其中的各个参数。 文生图是Stable Diffusion的核心功能&#xff0c;它的核心能力就是根据提示词生成相应的…

领域驱动设计:对象工厂

一、工厂概述 1.工厂与构造函数 许多面向对象语言都支持类通过构造函数创建它自己。 对象自己创建自己&#xff0c;就好像自己扯着自己的头发离开地球表面&#xff0c;完全不合情理&#xff0c;只是开发人员已经习以为常了。然而&#xff0c;构造函数差劲的表达能力与脆弱的…

Python轻量级Web框架Flask(12)—— Flask类视图实现前后端分离

0、前言&#xff1a; 在学习类视图之前要了解前后端分离的概念&#xff0c;相对于之前的模板&#xff0c;前后端分离的模板会去除views文件&#xff0c;添加两个新python文件apis和urls&#xff0c;其中apis是用于传输数据和解析数据 的&#xff0c;urls是用于写模板路径的。 …

基于Flask的岗位就业可视化系统(一)

前言 本项目综合了基本数据分析的流程&#xff0c;包括数据采集&#xff08;爬虫&#xff09;、数据清洗、数据存储、数据前后端可视化等 推荐阅读顺序为&#xff1a;数据采集——>数据清洗——>数据库存储——>基于Flask的前后端交互&#xff0c;有问题的话可以留言…

计算机网络面试高频:输入域名会发生那些操作,开放性回答

更多大厂面试内容可见 -> http://11come.cn 计算机网络面试高频&#xff1a;输入域名会发生那些操作&#xff0c;开放性回答 输入域名之后&#xff0c;会发生哪些操作&#xff1f; 当在浏览器中输入www.baidu.com并按下回车键时&#xff0c;会触发一系列复杂的网络过程&am…

Unity 物体触碰事件监听

声明委托 public delegate void MyDelegate(Collider trigger); C# 委托&#xff08;Delegate&#xff09; | 菜鸟教程 (runoob.com)https://www.runoob.com/csharp/csharp-delegate.html 定义委托 public MyDelegate onTriggerEnter; public MyDelegate onTriggerStay; pu…

Flask框架进阶-Flask流式输出和受访配置--纯净详解版

Flask流式输出&#x1f680; 在工作的项目当中遇到了一种情况&#xff0c;当前端页面需要对某个展示信息进行批量更新&#xff0c;如果直接将全部的数据算完之后&#xff0c;再返回更新&#xff0c;则会导致&#xff0c;前端点击刷新之后等待时间过长&#xff0c;开始考虑到用进…

怎么检查ubuntu22.04服务器机器被挖矿了

如果怀疑你的 Ubuntu 22.04 系统被挖矿程序占用&#xff0c;可以通过一系列检查步骤来确认这一疑问。这些步骤可以帮助你发现系统是否存在未授权的挖矿活动&#xff1a; 1. 检查CPU和GPU使用率 挖矿程序通常会导致CPU或GPU的使用率异常升高。使用以下命令检查系统资源的使用情…