C++零碎记录(三)

作者:小王同学在积累
链接:https://www.zhihu.com/question/437657370/answer/1692846096
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
 

5. 构造函数和析构函数

5.1 构造函数和析构函数的作用

① 构造函数:主要作用在于创建对象时为对象的成员属性赋值,构造函数由编译器自动调用,无须手动调用。

② 析构函数:主要作用在于对象销毁前系统自动调用,执行一些清理工作。

5.2 构造函数和析构函数的语法

① 构造函数语法:类名 () {}

1. 构造函数,没有返回值也不写void。
2. 函数名称与类名相同。
3. 构造函数可以有参数,因此可以重载。
4. 程序在调用对象时候会自动调用构造,无须手动调用,而且只会调用一次。

② 析构函数语法:~类名(){}

1. 析构函数,,没有返回值也不写void。
2. 函数名称与类名相同,在名称前加上符号。
3. 析构函数不可以有参数,因此不可以发生重载。
4. 程序在对象销毁前会自动调用析构,无须手动调用,而且只会调用一次。
#include <iostream>
using namespace std;
#include <string>//对象的初始化和清理
//1、构造函数 进行初始化操作class Person
{
public:  //无论是构造函数还是析构函数都是在public作用域下//1.1、构造函数//没有返回值 不用写void//函数名 与类名相同//构造函数可以有参数,可以发生重载//创建对象的时候,构造函数会自动调用,而且只调用一次Person(){cout << "Person 构造函数的调用" << endl;}/*如果你不写,编译器会自动创建一个,但是里面是空语句Person(){}*///1. 析构函数,,没有返回值也不写void。//2. 函数名称与类名相同,在名称前加上符号。//3. 析构函数不可以有参数,因此不可以发生重载。//4. 程序在对象销毁前会自动调用析构,无须手动调用,而且只会调用一次。~Person(){cout << "Person 析构函数的调用" << endl;}
};//构造和析构都是必须有的实现,如果我们自己不提供,编译器会提供一个空实现
void test01()
{Person p;  //创建对象的时候,自动调用构造函数//这个对象p是一个局部变量,是在栈上的数据,test01执行完,释放这个对象
}int main()
{//方式一:test01();   // 析构释放时机在test01运行完前,test01函数运行完后,里面的对象就被释放了/*方式二:     //创建对象的时候,自动调用构造函数Person p;   //只有构造函数,没有析构函数,只有main函数结束完前,对象要释放掉了,才会调用析构函数*/system("pause");return 0;}

运行结果:

  • Person 构造函数的调用
  • Person 析构函数的调用
  • 请按任意键继续. . .

5.3 构造函数的分类及调用

① 两种分类方式:

1. 按参数分为:有参构造和无参构造。
2. 按类型分为:普通构造和拷贝构造。

② 三种调用方式:

1. 括号法
2. 显示法
3. 隐式转换法
#include <iostream>
using namespace std;//1构造函数的分类及调用
//分类
//按照参数分类:无参构造(默认构造) 和 有参构造
class Person
{
public: //构造函数  编译器默认的构造函数是无参的Person(){cout << "Person 无参构造函数的调用" << endl;}Person(int a){age = a;cout << "Person 有参构造函数的调用" << endl;}//拷贝构造函数Person( const Person &p)  //用引用的方式传进来,不能改变原来的对象的属性,所以用const        {// 将传入的人人身上的所有属性,拷贝到我身上cout << "Person 拷贝构造函数的调用" << endl;age = p.age;}~Person(){cout << "Person 析构函数的调用" << endl;}int age;
};//调用
void test01()
{/*//1、括号法Person p1;       //默认构造函数调用Person p2(10);   //有参构造函数Person p3(p2);   //拷贝构造函数cout << "p2的年龄为:" << p2.age << endl;cout << "p3的年龄为:" << p3.age << endl;//注意事项1//调用默认构造函数的时候,不要加()。//下面这行代码,编译器会认为是一个函数的声明,像void func(),不会认为在创建对象。//Person p1();*//** //2、显示法Person p1;  //创建一个对象,这个对象调用的是无参构造Person p2 = Person(10); //有参构造  将匿名对象起了一个名称p2Person p3 = Person(p2); //创建一个对象,这个对象调用的是拷贝构造Person(10); //匿名对象 特点:当前行执行结束后,系统会立即回收匿名对象cout << "aaaa" << endl;  //通过打印时机可以得到:test还没结束,就运行析构函数了//注意事项2//不要利用拷贝构造函数 初始化匿名对象  编译器认为 Person(p3) 等价于 Person p3,//编译器会认为这是一个对象的声明,而上面已经有一个p3了,Person p3 = Person(p2);因此编译器认为重定义了       Person(p3);*///3、隐式转换法Person p4 = 10; //相当于 写了 Person p4 = Person(10);  调用有参构造Person p5 = p4; //调用拷贝构造}
int main()
{test01();system("pause");return 0;}

运行结果:

  • Person 有参构造函数的调用
  • Person 拷贝构造函数的调用
  • Person 析构函数的调用
  • Person 析构函数的调用
  • 请按任意键继续. . .

5.4 拷贝构造函数调用时机

① C++中拷贝构造函数调用时机通常有三种情况。

1. 使用一个已经创建完毕的对象来初始化一个新对象。
2. 值传递的方式给函数参数传值。
3. 以值方式返回局部对象。
#include <iostream>
using namespace std;//拷贝构造函数调用时机//1、使用一个已经创建完毕的对象来初始化一个新对象//2、值传递的方式给函数参数传值//3、值方式返回局部对象class Person
{
public:Person(){cout << "Person 默认构造函数调用" << endl;}Person(int age){m_Age = age;cout << "Person 有参构造函数调用" << endl;}Person(const Person& p){m_Age = p.m_Age;cout << "Person 拷贝构造函数调用" << endl;}~Person(){cout << "Person 析构函数调用" << endl;}int m_Age;};//1、使用一个已经创建完毕的对象来初始化一个新对象
void test01()
{Person p1(20);Person p2(p1);cout << "p2的年龄为:" << p2.m_Age << endl;
}//2、值传递的方式给函数参数传值
void doWork(Person p)
{}void test02()
{Person p;doWork(p);   //实参传给形参的时候,会调用拷贝构造函数,这个是值传递,是一个临时的副本//拷贝出去的p和原来的p 不是一个p
}//3、值方式返回局部对象
Person doWork2() //返回值类型为Person对象
{Person p1;   //局部对象cout << (int*)&p1 << endl;return p1;  //以值的方式返回一个拷贝的对象给外部,拷贝出一个对象p1'与原对象p1不一样,调用拷贝构造函数//程序运行结束,释放原p1,调用析构函数
}void test03()
{Person p = doWork2(); //这里没有调用拷贝构造函数,直接用p接收拷贝对象p1’cout << (int*)&p << endl;//程序运行结束,释放拷贝的对象p1',调用析构函数
}int main()
{//test01();	//test02();test03();system("pause");return 0;}

运行结果:

  • Person 默认构造函数调用
  • 005DF904
  • Person 拷贝构造函数调用
  • Person 析构函数调用
  • 005DF9FC
  • Person 析构函数调用
  • 请按任意键继续. . .

5.5 构造函数调用规则

5.5.1 构造函数调用规则

① 默认情况下,C++编译器至少给一个类添加3个函数。

1. 默认构造函数(无参,函数体为空)
2. 默认析构函数(无参,函数体为空)
3. 默认拷贝构造函数,对属性进行值拷贝

② 构造函数调用规则如下:

1. 如果用户定义有参构造函数,C++不再提供默认无参构造,但是会提供默认拷贝构造。
2. 如果用户定义拷贝函数,C++不会再提供其他构造函数。

③ 巧记法,如下图所示,如果定义中间的,上面的就默认不定义了,下面的默认定义。

5.5.2 调用定义的拷贝构造函数

#include <iostream>
using namespace std;//构造函数的调用规则
//1、创建一个类,C+=编译器会给每个类都添加至少3个函数
//默认构造 (空实现)
//析构函数 (空实现)
//拷贝构造 (值拷贝)class Person
{
public:Person(){cout << "Person 默认构造函数调用" << endl;}Person(int age){m_Age = age;cout << "Person 有参构造函数调用" << endl;}Person(const Person & p){m_Age = p.m_Age;cout << "Person 拷贝构造函数调用" << endl;}~Person(){cout << "Person 析构函数调用" << endl;}int m_Age;};void test01()
{Person p;p.m_Age = 18;Person p2(p);cout << "p2的年龄:" << p2.m_Age << endl;
}int main()
{test01();system("pause");return 0;}

运行结果:

  • Person 默认构造函数调用
  • Person 拷贝构造函数调用
  • p2的年龄:18
  • Person 析构函数调用
  • Person 析构函数调用
  • 请按任意键继续. . .

5.5.3 调用默认的拷贝构造函数

#include <iostream>
using namespace std;//构造函数的调用规则
//1、创建一个类,C+=编译器会给每个类都添加至少3个函数
//默认构造 (空实现)
//析构函数 (空实现)
//拷贝构造 (值拷贝)class Person
{
public:Person(){cout << "Person 默认构造函数调用" << endl;}Person(int age){m_Age = age;cout << "Person 有参构造函数调用" << endl;}//编译器自动提高拷贝构造函数~Person(){cout << "Person 析构函数调用" << endl;}int m_Age;};void test01()
{Person p;p.m_Age = 18;Person p2(p);  //调用编译器默认的拷贝构造函数会把p的所有属性拷贝过来cout << "p2的年龄:" << p2.m_Age << endl;
}int main()
{test01();system("pause");return 0;}

运行结果:

  • Person 默认构造函数调用
  • p2的年龄:18
  • Person 析构函数调用
  • Person 析构函数调用
  • 请按任意键继续. . .

5.5.4 调用定义的有参构造函数

#include <iostream>
using namespace std;//构造函数的调用规则
//1、创建一个类,C+=编译器会给每个类都添加至少3个函数
//默认构造 (空实现)
//析构函数 (空实现)
//拷贝构造 (值拷贝)class Person
{
public:Person(int age){m_Age = age;cout << "Person 有参构造函数调用" << endl;}//编译器自动提高拷贝构造函数~Person(){cout << "Person 析构函数调用" << endl;}int m_Age;};void test02()
{Person p; //如果写了有参构造函数,编译器就不再提供默认构造,依然提供拷贝构造构造//由于没有默认构造函数,所以报错Person p2(p);
}int main()
{test02();system("pause");return 0;}

5.5.5 调用定义的拷贝构造函数

#include <iostream>
using namespace std;//构造函数的调用规则
//1、创建一个类,C+=编译器会给每个类都添加至少3个函数
//默认构造 (空实现)
//析构函数 (空实现)
//拷贝构造 (值拷贝)class Person
{
public://如果写了拷贝构造函数,编译器就不再提供其他普通构造函数Person(const Person& p){m_Age = p.m_Age;cout << "Person 拷贝构造函数调用" << endl;}~Person(){cout << "Person 析构函数调用" << endl;}int m_Age;};void test01()
{Person p;    //没有默认构造函数,报错Person(10);  //没有有参构造函数,报错Person p2(p);cout << "p2的年龄:" << p2.m_Age << endl;
}int main()
{test01();system("pause");return 0;}

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

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

相关文章

【VR】Network Manager HUD

&#x1f4a6;本专栏是我关于VR开发的笔记 &#x1f236;本篇是——Network Manager HUD Network Manager HUD组件 简介基础知识 简介 网络管理器 HUD是一种快速启动工具&#xff0c;可帮助您立即开始构建多人游戏&#xff0c;而无需首先构建用于游戏创建/连接/加入的用户界面…

SpotBugs代码检查:在整数上进行没有起任何实际作用的位操作(INT_VACUOUS_BIT_OPERATION)

https://spotbugs.readthedocs.io/en/latest/bugDescriptions.html#int-vacuous-bit-mask-operation-on-integer-value-int-vacuous-bit-operation 在整数上进行无用的与、异或操作&#xff0c;实质上没有做任何有用的工作。 例如&#xff1a;v & 0xffffffff 再例如&…

聚观早报|小米14渲染图曝光;蚂蚁金融大模型正式发布

【聚观365】9月9日消息 小米14渲染图曝光 蚂蚁金融大模型正式发布 路特斯推出全电动轿车Emeya 上汽集团8月整车销量42.3万辆 ChatGPT网站流量连续三个月下滑 小米14渲染图曝光 高通旗下全新一代旗舰芯片骁龙8 Gen3将于10月24-26日举办的骁龙技术峰会上亮相&#xff0c;相…

《protobuf》基础语法

文章目录 消息体定义字段规则编译选项实战&#xff1a;编写一个通讯录文件 消息体定义 文件内定义 message Phone {string number 1; }message PeopleInfo {string name 1;int32 age 2;Phone phone 3; }内嵌定义 message PeopleInfo {string name 1;int32 age 2;messa…

Vue3_pinia使用

安装 cnpm install pinia 新建store目录&#xff0c;在store目录下创建loginUser.js import { defineStore } from pinia import {ref} from vue export const userLoginStore defineStore(loginUser, () > {let loginUserInfo ref({})function setUserInfo(data){this.…

Vue中如何实现城市3D分布图

cityfenbu.vue <template><div ><el-card class"seriesmap-box-card"><div slot"header" class"clearfix"><span>城市分布图 (点击可下钻到县)</span></div><div><div class"series-ma…

【科研论文配图绘制】task8 总结与回顾

task8 总结与回顾&#xff0c;这次组队学习大致掌握了常见python绘图工具包的使用&#xff0c;整体上和matlab的语法类似&#xff0c;也是用画布形式控制元素的绘制。印象深刻的是seaborn的使用&#xff0c;在之前做波士顿房价预测时候先接触了seaborn绘制的散点图、直方图和核…

【C++从0到王者】第二十八站:二叉搜索树的应用

文章目录 前言一、Key模型二、Key/Value模型总结 前言 二叉搜索树的在现实世界的应用很广泛&#xff0c;比如Key模型&#xff0c;Key-Value模型就是常见的两种的模型 一、Key模型 K模型&#xff1a;K模型即只有key作为关键码&#xff0c;结构中只需要存储Key即可&#xff0c…

适用于Linux的Windows子系统(系统安装步骤)

目录 前言 一、WSL2安装 1.Microsoft参考文档&#xff08;推荐选择旧版 WSL 的手动安装步骤&#xff09; 2.开启子系统 二、Ubuntu安装 1.在Microsoft Store中获取ubuntu 2.运行ubuntu配置管理信息 3.ubuntu换源 三、WSL 与 Ubuntu的一些基础使用命令 四、Windows Terminal终端…

C++新特性:智能指针

一 、为什么需要智能指针 智能指针主要解决以下问题&#xff1a; 1&#xff09;内存泄漏&#xff1a;内存手动释放&#xff0c;使用智能指针可以自动释放 2&#xff09;共享所有权指针的传播和释放&#xff0c;比如多线程使用同一个对象时析构问题&#xff0c;例如同样的数据…

C#,《小白学程序》第十八课:随机数(Random)第五,方差及标准方差(标准差)的计算方法与代码

1 文本格式 /// <summary> /// 《小白学程序》第十八课&#xff1a;随机数&#xff08;Random&#xff09;第五&#xff0c;方差及标准方差&#xff08;标准差&#xff09;的计算方法与代码 /// 方差 SUM(&#xff08;Xi - X)^2 ) / n i0...n-1 X Average of X[i] ///…

《DevOps实践指南》- 读书笔记(二)

DevOps实践指南 Part 2 从何处开始5. 选择合适的价值流作为切入点5.1 绿地项目与棕地项目5.2 兼顾记录型系统和交互型系统5.3 从最乐于创新的团队开始5.4 扩大 DevOps 的范围5.5 小结 6. 理解、可视化和运用价值流6.1 确定创造客户价值所需的团队6.2 针对团队工作绘制价值流图6…

【广州华锐互动】电厂三维数字孪生大屏的功能和优势

在工业互联网的背景下&#xff0c;电厂三维数字孪生大屏系统正在逐渐成为电力行业的重要技术。通过创建电厂的虚拟模型&#xff0c;这个数字孪生系统可以实现对实际电厂的实时监控&#xff0c;预测维护需求&#xff0c;优化运营效率&#xff0c;甚至在某些情况下&#xff0c;能…

jmeter 线程组 Open Model Thread Group 阶梯式压测、高峰流量压测

简介 Open Model Thread Group 是5.4.1 版本中引入的一个实验性线程组&#xff0c;可以弹性模拟负载测试。例如设置多个线程模式&#xff0c;再根据这些线程模式调整不同的并发数、暂停时间。由于Open Model Thread Group 是一个实验性线程组&#xff0c;可能会存在一些限制和不…

2.9 PE结构:重建导入表结构

脱壳修复是指在进行加壳保护后的二进制程序脱壳操作后&#xff0c;由于加壳操作的不同&#xff0c;有些程序的导入表可能会受到影响&#xff0c;导致脱壳后程序无法正常运行。因此&#xff0c;需要进行修复操作&#xff0c;将脱壳前的导入表覆盖到脱壳后的程序中&#xff0c;以…

【群智能算法改进】一种改进的鹈鹕优化算法 IPOA算法[2]【Matlab代码#58】

文章目录 【获取资源请见文章第5节&#xff1a;资源获取】1. 原始POA算法2. 改进后的IPOA算法2.1 随机对立学习种群初始化2.2 动态权重系数2.3 透镜成像折射方向学习 3. 部分代码展示4. 仿真结果展示5. 资源获取 【获取资源请见文章第5节&#xff1a;资源获取】 1. 原始POA算法…

【JavaScript】在指定dom元素前面创建标签元素

一、基础操作过程 要在指定的DOM元素前面创建标签元素&#xff0c;有以下步骤&#xff1a; 获取指定的DOM元素&#xff1a;使用document.querySelector()或document.getElementById()等方法来获取指定的DOM元素。 const targetElement document.querySelector(#targetElement…

数字展厅有什么优势,一文了解数字展厅建设方案

引言&#xff1a; 在当今数字化风潮的席卷下&#xff0c;企业们正积极寻求创新的方式来吸引和互动他们的客户。数字展厅作为一种新型的虚拟宣传工具&#xff0c;已经开始引起广泛的关注。 一&#xff0e;什么是数字展厅&#xff1f; 数字展厅是一种基于虚拟现实&#xff08;V…

【前端】在Vue页面中引入其它vue页面 数据传输 相互调用方法等

主页面 home 从页面 headView 需求 在 home.vue 中引用 headView.Vue 方案: home.vue 代码: 只需要在home.vue 想要的地方添加 <headView></headView> <script>//聊天页面 import headView /view/headView.vueexport default {components: {headView},…

淘宝商品销量接口API更新(总销+精准月销API)

不少客户有获取淘宝商品销量的需求&#xff0c;淘宝商品销量接口主要用于以下业务场景。有不齐全的欢迎大家补充。 库存管理&#xff1a;商家可以通过接口获取到实时的销量信息&#xff0c;更好地进行库存管理。供应链计划&#xff1a;商家可以通过接口了解到商品的销售趋势&a…