C++语法|如何写出高效的C++代码(一)|对象使用过程中背后调用了哪些方法(构造和析构过程)?

文章目录

  • 再探拷贝构造函数和重载复制运算符
    • 实例化新对象和赋值操作
    • 强转为类类型
    • 指针和引用时临时对象的构造和析构过程
  • 考考你
    • 问题
    • 答案

再探拷贝构造函数和重载复制运算符

实例化新对象和赋值操作

首先我们写一个类,实现它的拷贝构造并重载赋值运算符。

class Test {
private:
	int ma;
public:
	Test(int a = 10): ma(a) {
		cout << "Test()构造函数" << endl;
	}
	~Test() {
		cout << "~Test析构函数" << endl;
	}
	Test(const Test& t) {
		cout << "Test const Test& t拷贝构造函数" << endl;
	}
	Test& operator=(const Test& t) {
		ma = t.ma;
		cout << "operator = 重载赋值运算符" << endl;
		return *this;
	}
};

然后我们构造类的对象,主要探究什么时候调用重载赋值运算符、什么时候调用拷贝构造

int main () {
	Test t1;
	Test t2(t1);
	Test t3 = t2;
	Test t4 = Test(20);
	cout << "-------------" << endl;
	return 0;
}

结果如下:

为什么没有调用我们的t3和t4没有调用重载赋值运算符呢?

首先t3调用的是拷贝构造函数,说明本质上这是一条构造语句,如果写成

Test t3;
t3 = t2; // 这里调用了重载的赋值运算符

再一个t4是直接调用构造函数,那是因为Test(20)显示生成临时对象,它的生命周期为所在语句,所以它被编译器优化了,实际上调用的是Test t4(20);,如果写成:

//t4.operator=(t2)
t4 = t2; //赋值,没有生成新对象
// t4.operator=(const Test &t)
t4 = Test(20); //这个临时对象会构造一个新对象,然后赋值给t4

此处的Test(20)会就会调用构造函数了,并且t4=会调用重载赋值构造函数,也就是说,只要我们不是在进行初始化对象,而是在赋值某个对象的话,就会调用重载赋值运算符。

强转为类类型

接着上面的代码

t4 = (Test)30; // int->Test

这样能转吗?其实是可以的,编译器会寻找Test类是否有一个合适的构造函数。显然我们这里是有的,因为我们的构造函数默认输入一个整形变量,所以编译器会为我们生成一个临时对象。甚至我们可以写成:这样的话我们是隐式生成临时对象。

t4 = 30;
//t4 = "aaa"; 报错,因为我们没有实现带char*类型的构造函数

指针和引用时临时对象的构造和析构过程

我们想考察一下指针和引用来获取临时对象:

Test *p = &Test(40);
//p指向的是一个已经析构的临时对象,该指针变为野指针
const Test &ref = Test(40);
//Test &ref = Test(30); 报错,必须是常引用

这里的指针甚至不能编译,这是由于较新的编译器代码检查机制更加严格,放以前肯定就编译通过了。并且该指针一定会成为野指针,因为出语句之后临时对象就会析构。并且较新的编译器const Test &ref = Test(40)也会报错,报错语句为:

error: taking the address of a temporary object of type 'Test' [-Waddress-of-temporary]

结论:在较新版本的编译器中,无论是用常引用还是指针,都不能指向一个临时对象

考考你

问题

对于以下类:

class Test {
public:
	// Test() Test(a) Test(b)
    Test(int a = 5, int b = 5) : ma(a), mb(b) {
        cout << "Test()构造函数" << endl;
    }
    ~Test() {
        cout << "~Test()析构函数" << endl;
    }
    Test(const Test& src) : ma(src.ma), mb(src.mb) {
        cout << "Test(const Test&)拷贝构造函数" << endl;
    }

    Test& operator=(const Test& src) {
        ma = src.ma;
        mb = src.mb;
        cout << "operator=(const Test&)重载赋值运算符" << endl;
        return *this;
    }
private:
    int ma;
    int mb;
};

我们这样实例化这个类,请问每条语句都调用了类的哪些成员函数呢?

Test t1(10, 10);//1.Test(int, int)
int main() {
	Test t2(20, 20);//3.Test(int, int)
	Test t3 = t2; //4.Test(const Test&)
	/*
	静态变量和全局变量程序运行的时候内存就已经存在了,
	因为数据段内存是事先就分配好的
	但是静态局部变量只在第一次运行到它才会初始化,所以并不会构造先t4
	*/
	//static Test t4(30,30);
	static Test t4 = Test(30, 30);//5.Test(int, int)
	t2 = Test(40, 40); //6.Test(int, int) operator= ~Test()
	//(50, 50) = 50 逗号表达式
	t2 = (Test)(50, 50);//7.(Test)50; Test(int, int) operator= ~Test()
	t2 = 60;	// Test(int) 8.Test(int, int) operator= ~Test()
	Test *p1 = new Test(70, 70); //9. Test(int, int)
	Test *p2 = new Test[2]; // 10. Test(int, int) Test(int, int)
	//较新的编译器无法通过编译
	Test *p3 = &Test(80, 80);  //11.Test(int, int) ~Test()
	const Test &p4 = Test(90, 90); //12.Test(int, int)
	delete p1; //13.~Test() 然后free内存
	delete[]p2; //14.~Test() ~Test() 然后free内存
}
Test t5(100, 100); //2. Test(int, int)

运行以后,这个类的构造、析构、拷贝构造的调用过程已经写在注释中了,并且最后的析构顺序为p1->p2->p4->t3->t2->t4->t5->t1 一共应该是9连析构

答案

你答对了吗?(这里的输出结果是注释Test *p3 = &Test(80, 80);后的结果)

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

封装Springboot基础框架功能-03

在些模块中汇总了一些web开发常用的配置和功能。 模块源码结构 Restful API常用定义 QueryParam请求参数 Data public class QueryParam {private String key;private String value; }RestfulController实现 RestfulController.java&#xff0c;主要汇总一些常用的restful的…

【C++】C++11--- 列表初始化|关键字

目录 前言 列表初始化 创建对象时的列表初始化 单参数隐式类型转换 多参数的隐式类型转换 new表达式中使用列表初始化 列表初始化适用于STL 容器 模板类initializer_list 关键字auto 关键字decltype 关键字nullptr 前言 C标准10年磨一剑&#xff0c;第二个真正意义上…

探索网站支付系统的奥秘,从Vue3和Spring Boot开始(入门级项目实战+在线教程)附赠项目源码!

你是否曾经在购物时&#xff0c;对着电脑屏幕前的“支付成功”四个字感到好奇&#xff1f;这背后的秘密究竟是什么&#xff1f; 今天&#xff0c;让我们一起揭开支付系统的神秘面纱&#xff0c;探索其背后的技术实现。 在这个基于Vue3和Spring Boot的支付项目实战中&#xff…

ChatGLM-Math:强化数学能力

大型语言模型&#xff08;LLM&#xff09;在文本摘要、问答和角色扮演对话等语言任务上表现出色&#xff0c;在数学推理等复杂问题上也具有应用潜力。 但目前提高 LLM 数学问题解决能力的方法&#xff0c;往往会导致其他方面能力的下降。例如RLHF的方法&#xff0c;虽然可以提…

Linux的虚拟机操作

一、linux系统 我们知道的系统用到的大多数是Windows系统。 Windows个人用到的有&#xff1a;win7 win10 win11 winxp 服务器用到的有&#xff1a;windows server 2003、2008、2013...........等等 linux也有系统。 centos 7 有5、6、8等等 redhat ubuntu kail 二、了…

Apple强大功能:在新款 iPad Pro 和 iPad Air 中释放 M4 芯片潜力

Apple 的最新强大功能&#xff1a;在新款 iPad Pro 和 iPad Air 中释放 M4 芯片的潜力 概述 Apple 推出配备强大 M4 芯片的最新 iPad Pro 和 iPad Air 型号&#xff0c;再次突破创新界限。新一代 iPad 有望彻底改变我们的工作、创造和娱乐方式。凭借无与伦比的处理能力、令人惊…

kubebuilder(6)webhook

operator中的webhook也是很重要的一块功能。也是相对比较独立的模块&#xff0c;所以放在后面讲。 webhook是一个callback&#xff0c;注册到k8s的api-server上。当某个特定的时间发生时&#xff0c;api server就会查询注册的webhook&#xff0c;并根据一些逻辑确认转发消息给…

练习题(2024/5/8)

1 二叉树的最近公共祖先 给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。 百度百科中最近公共祖先的定义为&#xff1a;“对于有根树 T 的两个节点 p、q&#xff0c;最近公共祖先表示为一个节点 x&#xff0c;满足 x 是 p、q 的祖先且 x 的深度尽可能大&#xff08;…

第2章.STM32开发C语言常用知识点

目录 0. 《STM32单片机自学教程》专栏总纲 2.1. STM32嵌入式开发C语言编程的不同 2.2. C语言常用知识点 2.2.1 位操作 2.2.2 define 宏定义 2.2.3 条件编译 2.2.3.1 #ifdef 2.2.3.2 #ifndef 2.2.3.3 #if !defined 2.2.4 extern 变量声明 2.2.5 typedef 类型别名 …

微信用户可以通过哪些渠道查找和关注到公众号

什么是公众号 公众号&#xff0c;作为微信生态中不可或缺的一部分&#xff0c;已经成为连接用户与品牌、企业与个人的重要桥梁。它不仅是一个信息发布平台&#xff0c;更是一个集互动、服务、营销于一体的综合性工具。公众号通过发布高质量的内容&#xff0c;吸引用户关注&…

Leetcode—976. 三角形的最大周长【简单】(ranges::sort函数)

2024每日刷题&#xff08;122&#xff09; Leetcode—976. 三角形的最大周长 实现代码 class Solution { public:int largestPerimeter(vector<int>& nums) {ranges::sort(nums);for(int i nums.size() - 1; i > 1; i--) {if(nums[i - 1] nums[i - 2] > nu…

项目经理【过程】原则

系列文章目录 【引论一】项目管理的意义 【引论二】项目管理的逻辑 【环境】概述 【环境】原则 【环境】任务 【环境】绩效 【人】概述 【人】原则 【人】任务 【人】绩效 【过程】概念 【过程】原则 一、质量管理水平、质量管理的发展 1.1 质量管理水平 1.2 质量管理的发展 …

亲测快捷高效的编写测试用例方法

前言 测试用例是任何测试周期的第一步&#xff0c;对任何项目都非常重要。如果在此步骤中出现任何问题&#xff0c;则在整个软件测试过程中都会扩大影响。如果测试人员在创建测试用例模板时使用正确的过程和准则&#xff0c;则可以避免这种情况。 在本篇文章中将分享一些简单而…

【大学物理】双语合集听课笔记

7.5 angular momentu(角动量)_哔哩哔哩_bilibili 6.4Energy in Rotation Motion 有质量有速度的物体有动能&#xff0c;是不是很有道理 international system&#xff08;from French systeme international&#xff0c;acronym&#xff0c;SI&#xff09;of ineria kg*m^2 转…

[笔试训练](十六)

目录 046:字符串替换 047:神奇数 048:DNA序列 046:字符串替换 字符串替换_牛客题霸_牛客网 (nowcoder.com) 题目&#xff1a; 题解&#xff1a; 简单模拟题~ class StringFormat { public:string formatString(string str, int n, vector<char> arg, int m) {strin…

PPP点对点协议

概述 Point-to-Point Protocol&#xff0c;点到点协议&#xff0c;工作于数据链路层&#xff0c;在链路层上传输网络层协议前验证链路的对端&#xff0c;主要用于在全双工的同异步链路上进行点到点的数据传输。 PPP主要是用来通过拨号或专线方式在两个网络节点之间建立连接、…

牛客 二叉树 NB1 牛群的最大高度

原题链接 就不采用, 递归的方式来做了, 自己弄个栈来做 用栈来保存路径, curr 表示当前的节点, pre 保留往回走时的上一步 如果是 用递归来做 它的栈链路是这样的, 可以做下参考 黄色表示返回 用栈模拟的话, 不可能模拟得一摸一样, 递归的话一个栈会经过3次, 第三次后就不…

MATLAB实现遗传算法优化第三类生产线平衡问题

第三类生产线平衡问题的数学模型 假设&#xff1a; 工作站数量&#xff08;m&#xff09;和生产线节拍&#xff08;CT&#xff09;是预设并固定的。每个任务&#xff08;或作业元素&#xff09;只能分配到一个工作站中。任务的执行顺序是预先确定的&#xff0c;且不可更改。每…

ICode国际青少年编程竞赛- Python-2级训练场-列表入门

ICode国际青少年编程竞赛- Python-2级训练场-列表入门 1、 Dev.step(3)2、 Flyer.step(1) Dev.step(-2)3、 Flyer.step(1) Spaceship.step(7)4、 Flyer.step(5) Dev.turnRight() Dev.step(5) Dev.turnLeft() Dev.step(3) Dev.turnLeft() Dev.step(7) Dev.turnLeft() Dev.…

二叉树习题汇总

片头 嗨&#xff01;大家好&#xff0c;今天我们来练习几道二叉树的题目来巩固知识点&#xff0c;准备好了吗&#xff1f;Ready Go ! ! ! 第一题&#xff1a;二叉树的最大深度 解答这道题&#xff0c;我们采用分治思想 1. 递归子问题&#xff1a;左子树的高度和右子树的高度 …
最新文章