构造,析构,拷贝构造

1. 类的6个默认的成员变量

如果一个类中什么成员都没有,简称为空类,空类中什么都没有?并不是的,任何一个类在我们不写的情况下,都会自动生成下面6个默认成员函数。
在这里插入图片描述
注意:这里的“默认”和“缺省”的意思差不多,也就是你不写这6个函数,编译器会自动生成,你若是写了,则编译器就不生成了。

2. 构造函数

2.1 概念

概念:构造函数是一个特殊的成员函数,名字与类名相同,创建类类型对象时由编译器自动调用,保证每个数据成员都有 一个合适的初始值,并且在对象的生命周期内只调用一次。

2.2 特性

构造函数是特殊的成员函数,需要注意的是,构造函数的虽然名称叫构造,但是需要注意的是构造函数的主要任务并不是开空间创建对象,而是初始化对象

其特征如下:

· 函数名与类名相同
· 无返回值
· 对象实例化编译器自动调用对应的构造函数
· 构造函数可以重载

class Date
{
public:// 构造函数// 1.无参构造函数Date(){}// 2. 有参构造Date(int year, int month, int day){_year = year;_month = month;_day = day;}// 3.全缺省//Date(int year = 1, int month = 1, int day = 1){_year = year;_month = month;_day = day;}//
private:int _year;int _month;int _day;
};
void test(){Date d1;//调用无参构造函数Date d2(2022,1,18);//调用带参的构造函数
}

注意:如果类中没有显示定义构造函数,则在类实例化的时候, C++编译器会自动生成一个无参的默认构造函数,一旦用户显示定义编译器将不再自动生成.
默认构造函数有三种:

  1. 编译器默认生成的构造函数(对内置类型不会处理,还是随机值;对于自定义类型会去调用他们自己的构造函数初始化);
  2. 全缺省构造函数
  3. 无参构造函数

3. 析构函数

3.1 概念

概念:**局部对象销毁工作是由编译器完成的。**而对象在销毁时会自动调用析构函数,完成类的一些资源清理工作。

实例化对象:(栈是后进先出 ;堆是先进先出)
在这里插入图片描述
例如:

class A
{
public:A(){cout << "A()" << endl;}~A(){cout << "~A()" << endl;}
private:int _a;
};class B
{
public:B(){cout << "B()" << endl;}~B(){cout << "~B()" << endl;}
private:int _b;
};int main()
{A a;B b;return 0;
}
// 因为对象是定义在函数中,函数调用会建立栈帧,// 栈帧中的对象构造和析构也要很符合后进先出。// 所以这里的顺序是: A()->B()->~B()->~A()

运行结果:
在这里插入图片描述

4. 拷贝构造函数

4.1 概念

拷贝构造函数也是构造函数的一种。普通的构造函数可以是无参的,也可以是有参的。但是拷贝构造函数必须是有参的,如下所示,参数就是const类型的对象引用:

class Car
{
public:Car() // 普通的构造函数{cout << "Car()" << endl;}Car(const Car &car)	 // 拷贝构造函数,参数是const类型的对象引用{cout << "Car():(const Car &car)" << endl;}};

那什么时候调用拷贝构造函数呢?
回答:
当利用已存在的对象创建一个新对象时(拷贝对象),就会调用新对象的拷贝构造函数进行初始化新对象的成员变量。

int main()
{//创建对象,调用普通的构造函数 Car car1; //cout << "Car()" << endl;// 利用已经存在的对象,创建新对象,叫做拷贝对象,拷贝对象创建,就会调用拷贝构造函数Car car2(car1);	 // cout << "Car():(const Car &car)" << endl;getchar();return 0;
}
4.2 拷贝了什么?

拷贝了内存中的东西!也就是可瓯北了原有对象的成员。

class Car
{int m_price;int m_length;
public:Car(int price = 0 ,int length = 0): m_price(price),m_length(length)	// 普通的构造函数{cout << "Car():m_price(price),m_length(length)" << endl;}void display(){cout << "m_price = " << m_price << " m_length = " << m_length << endl;}};int main()
{Car car3(100, 20);car3.display();// 利用已经存在的对象,创建新对象,叫做拷贝对象Car car4(car3);	car4.display(); // m_price = 100 m_length =20return 0;
}

此时car4对象内存空间里,也有这两个成员变量,且都有值。这就叫对象的拷贝操作,把对象里的成员变量都拷贝过来,成员变量的值也拷贝过来。注意:此时,我在类中并没有声明拷贝构造函数。

car4依然可以把car3里的成员变量拷贝过来。就类似于下面的拷贝方式,直接把car3对象的值赋值给car4。

当我再次拷贝car3对象时,car4打印的成员变量值是乱码,意味着并没有讲car3的值拷贝过来

Car car4(car3);	
car4.display(); // m_price = -827381223 m_length =-827381223
4.3 拷贝构造函数的功能

拷贝构造函数既然是构造函数的一种,那必然是用来初始化成员变量的。既然是拷贝构造函数,那必然是用来初始化拷贝对象的成员变量的(也就是我们例子中的car4对象)。当我在类中自己定义拷贝构造函数,那也就意味着系统默认的拷贝操作不存在了,因为会调用自己默认的拷贝构造函数。

我们想要解决刚才的那个问题,只需要在拷贝构造函数里将传进来的对象的成员变量赋值给当前对象的成员变量即可(不写this也行)。

class Car
{int m_price;int m_length;
public:Car(int price = 0 ,int length = 0): m_price(price),m_length(length)	// 普通的构造函数{cout << "Car():m_price(price),m_length(length)" << endl;}Car(const Car &car)	 // 拷贝构造函数{cout << "Car():(const Car &car)" << endl;this->m_price = car.m_price;  // 将传进来的car的对象,传递给新创建的对象,不写this一样this->m_length = car.m_length;}void display(){cout << "m_price = " << m_price << " m_length = " << m_length << endl;}
};

这样再次拷贝的时候,就调用默认自定义的拷贝构造函数了。

Car car4(car3);	//将car4的地址值,传递给拷贝构造函数的this指针
car4.display(); // m_price = 100 m_length =20
4.4 为什么要有拷贝构造函数

(思考浅拷贝,深拷贝的问题)
如果我在类中定义了拷贝构造函数,那么拷贝对象创建的时候,就会直接调用自定义的拷贝构造函数。假如,此时拷贝构造函数里没有成员变量的拷贝,那结果就不会有成员变量的拷贝

如果我在类中没有定义拷贝构造函数,当我拷贝对象创建的时候,就会默认对成员变量进行拷贝,就不要额外写成员变量拷贝的代码

所以,如果重写拷贝构造函数,就必须自己手动的进行成员变量的拷贝。如果没有重写拷贝构造函数,那就啥事也没有,编译器会默认帮你拷贝类中所有的成员变量。

通过上面的例子发现,似乎不重写拷贝构造函数也能完成对象的拷贝。同时,写了拷贝构造函数之后,还需要手动的完成赋值操作,反而麻烦了。

但拷贝构造函数的奥义远不如此,我们这里先埋下一个伏笔,等我们了解了浅拷贝和深拷贝之后,再来回答这个问题。(如果类内成员变量都是基本数据类型:int、double…,不写拷贝构造函数完全没有问题)

导航回来,意味着我们了解了深拷贝和浅拷贝的区别。回答我们提出的问题:为什么要写拷贝构造函数?

当类中的成员变量有指针变量时,如果不重写拷贝构造函数,编译器默认的拷贝操作是浅拷贝操作。也就意味着仅仅将指针变量的地址值拷贝过去,而不会将指针指向存储空间里的内容拷贝过去。

所以,当类中成员变量有指针变量时,如果想要实现拷贝对象操作,则必须重写拷贝构造函数。

参考:
https://blog.csdn.net/weixin_45452278/article/details/125397565

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/257934.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Flask template+Vue +项目中include引入其他模版(其他模版也会用到vue)的使用探索

项目背景是&#xff1a;团队的历史项目&#xff0c;是flask tmeplate写的前段页面。然后我在一个页面A.html中引入了vue文件&#xff0c;使用了vueelement_ui技术。现在想在此A页面中插入另外一个页面B.html的内容&#xff08;试图tab分开&#xff09;&#xff0c;因为入口只有…

No suitable driver found for jdbc:mysql://localhost:3306(2023/12/7更新)

有两种情况&#xff1a; 压根没安装下载了但没设为库或方法不对 大多数为第一种情况&#xff1a; 一. 下载jdbc 打开网址选择一个版本进行下载 https://nowjava.com/jar/version/mysql/mysql-connector-java.html 二.安装jdbc 在项目里建一个lib文件夹 在把之前下载的jar文…

免费的数据采集软件,最新免费的几款数据采集软件【2024】

在当今数字化时代&#xff0c;数据是企业决策和业务发展的关键。而如何高效获取数据成为许多企业和研究机构的关注焦点。本文将深入探讨数据采集软件的种类。帮助大家选择最适合自己需求的数据采集工具。 数据采集软件种类 在众多数据采集软件中&#xff0c;有一类强大而多样…

《一念关山》热度破万,爱奇艺古装赛道出尽风头

​刘诗诗重回古装剧、新式武侠公路片、质感细腻的镜头美学......看点满满的《一念关山》频频登上热搜&#xff0c;俘获了大批观众的心。 开播首日热度就刷新了爱奇艺2023年站内纪录&#xff0c;《一念关山》作为2023年爱奇艺在古装赛道的收官之作&#xff0c;口碑和热度兼收。…

RHEL网络服务器

目录 1.时间同步的重要性 2.配置时间服务器 &#xff08;1&#xff09;指定所使用的上层时间服务器。 (2&#xff09;指定允许访问的客户端 (3&#xff09;把local stratum 前的注释符#去掉。 3.配置chrony客户端 &#xff08;1&#xff09;修改pool那行,指定要从哪台时间…

LV.12 D24 陀螺仪实验 学习笔记

一、陀螺仪实验代码分析 设置GPB_2引脚和GPB_3引脚功能为I2C传输引脚 #include "exynos_4412.h"/****************MPU6050内部寄存器地址****************/#define SMPLRT_DIV 0x19 //陀螺仪采样率&#xff0c;典型值&#xff1a;0x07(125Hz) #define CONFIG 0x1A…

SAP UI5 walkthrough step9 Component Configuration

在之前的章节中&#xff0c;我们已经介绍完了MVC的架构和实现&#xff0c;现在我们来讲一下&#xff0c;SAPUI5的结构 这一步&#xff0c;我们将所有的UI资产从index.html里面独立封装在一个组件里面 这样组件就变得独立&#xff0c;可复用了。这样&#xff0c;无所什么时候我…

基于SpringBoot+Vue学生成绩管理系统前后端分离(源码+数据库)

一、项目简介 本项目是一套基于SpringBootVue学生成绩管理系统&#xff0c;主要针对计算机相关专业的正在做bishe的学生和需要项目实战练习的Java学习者。 包含&#xff1a;项目源码、数据库脚本等&#xff0c;该项目可以直接作为bishe使用。 项目都经过严格调试&#xff0c;确…

为“异常”努力是值得的

异常是OO语言处理错误的方式,在C中&#xff0c;鼓励使用异常。侯捷再书中谈起异常&#xff0c;“十年前撰写“未将异常考虑在内的”函数是为一种美好实践&#xff0c;而今我们致力于写出“异常安全码”。”可见异常安全的重要。 说起异常安全&#xff0c;首先就要是异常的出现…

自定义GPTs的Actions 调用外部API测试 返回API的结果:成功

我的自定义GPT&#xff1a;https://chat.openai.com/g/g-sOqIFZgIy-superbrain 效果&#xff1a;chatGPT调用我的天气接口返回天气。 可以看见把json结果变成md格式(人方便阅读)了。与物理世界连接成功&#xff0c;太强大了。 我建的测试示例&#xff1a;https://3.wjsou.…

王炸升级!PartyRock 10分钟构建 AI 应用

前言 一年一度的亚马逊云科技的 re:Invent 可谓是全球云计算、科技圈的狂欢&#xff0c;每次都能带来一些最前沿的方向标&#xff0c;这次也不例外。在看完一些 keynote 和介绍之后&#xff0c;我也去亲自体验了一些最近发布的内容。其中让我感受最深刻的无疑是 PartyRock 了。…

物联网+AI智慧工地云平台源码(SaaS模式)

智慧工地云平台充分运用数字化技术&#xff0c;聚焦施工现场岗位一线&#xff0c;依托物联网、互联网、AI等技术&#xff0c;围绕施工现场管理的人、机、料、法、环五大维度&#xff0c;以及施工过程管理的进度、质量、安全三大体系为基础应用&#xff0c;实现全面高效的工程管…