C++技能系列 ( 4 ) - 深入理解C++临时对象【解析与提高性能手段】

news2024/11/15 11:14:53

系列文章目录

C++技能系列
C++高性能优化编程系列
深入理解软件架构设计系列
高级C++并发线程编程

期待你的关注哦!!!
在这里插入图片描述

现在的一切都是为将来的梦想编织翅膀,让梦想在现实中展翅高飞。
Now everything is for the future of dream weaving wings, let the dream fly in reality.

深入理解C++临时对象

  • 系列文章目录
  • 一、产生临时对象的情况
    • 1.1 以值的方式给函数传递参数 - 如何优化呢?
    • 1.2 类型转换生成的临时对象 - 如何优化呢?
      • 1.2.1 类型转换生成的临时对象
      • 1.2.2 隐式类型转换以保证函数调用成功
    • 1.4 函数返回值的时候 - 如何优化呢?
  • 二、小结

有些临时对象是系统自己产生的,又有一些临时对象却是因为代码的书写问题而产生的,因为临时对象会额外消耗系统资源,所以编写代码的原则就是产生的临时对象越少越好。临时对象一般都是在栈上,所以一般都不会手动去释放。

为什么要了解临时对象?因为临时对象的产生和销毁都是有成本的,都会影响程序的执行性能和效率,所以如果能有效地减少临时对象的产生,那么无疑意味着程序性能和效率的提升。

一、产生临时对象的情况

1.1 以值的方式给函数传递参数 - 如何优化呢?

先看如下案例:

class CTempValue
{
public:
    int val1;
    int val2;
public:
    //构造函数
    CTempValue(int v1 = 0, int v2 = 0)
    {
        cout << "调用构造函数" << endl;
        val1 = v1;
        val2 = v2;
        cout << "val1 = " << val1 << endl;
        cout << "val2 = " << val2 << endl;
    }
    ~CTempValue()
    {
        cout << "调用了析构函数" << endl;
    }
    //拷贝构造函数
    CTempValue(const CTempValue& t)
    {
        cout << "调用拷贝构造函数" << endl;
        val1 = t.val1;
        val2 = t.val2;
        cout << "val1 = " << val1 << endl;
        cout << "val2 = " << val2 << endl;
    }
    int Add(CTempValue tobj)
    {
        int tmp = tobj.val1 + tobj.val2;
        tobj.val1 = 1000;   //这里的修改对外界没有影响
        return tmp;
    }
};

int main()
{
	CTempValue tm(10, 20);  //调用构造函数
	int Sum = tm.Add(tm);   // 这会调用拷贝构造函数的执行
	cout << "Sum = " << Sum << endl;  //Sum = 30
	cout << "tm.val1 = " << tm.val1 << endl; //tm.val1 = 10
	return 0;
}

运行结果如下:

调用构造函数
调用拷贝构造函数
调用了析构函数
Sum = 30
tm.val1 = 10
调用了析构函数

⚠️请注意,结果中调用了拷贝构造函数,为什么调用CTempValue类的拷贝构造函数呢?

这是因为调用Add成员函数时把对象tm传递给了Add成员函数,此时,系统会调用拷贝构造函数创建一个副本tobj(成员函数Add的形参),用于在函数体Add内使用,因为tm对象的vall值(tm对象的vall值仍旧为10)。

形参tobj是一个局部对象(局部变量),从程序功能的角度来讲,函数体内需要临时使用它一下,来完成一个程序上的一个功能,它确实是一个局部变量,只能在Add函数体里使用。所以严格意义来讲,它又不能称为一个真正意义的临时对象,因为真正的临时对象往往指的是真实存在,但又感觉不到的对象(至少从代码上不能直接看到的对象)

但是,对于目前确实生成了tobj对象,并且调用了类的拷贝构造函数,有了复制的动作,就会影响程序的执行效率。

那如何优化呢?

我们可以使用引用:

int Add(CTempValue& tobj){}

1.2 类型转换生成的临时对象 - 如何优化呢?

1.2.1 类型转换生成的临时对象

接下来,我们看下真正意义的临时对象,因为这个临时对象确实存在,但是从程序代码的角度不能直接看到它。

CTempValue sum;
sum = 1000;

执行一下,程序结果如下:

调用构造函数
val1 = 0
val2 = 0
调用构造函数
val1 = 1000
val2 = 0
调用了析构函数
调用了析构函数

在执行sum = 1000;系统调用了一次CTempValue类的构造函数和析构函数,这说明系统肯定产生了一个对象,但这个对象在哪里,通过代码完全看不到,所以这个对象是一个真正的临时对象。

那么,产生这个临时对象的原因是什么呢?

是因为把1000赋给sum,而sum本身是一个CTempValue类型的对象,1000是一个数字,那怎么把数字能转化成CTempValue类型的对象呢?所以编译器这里帮助我们以1000为参数调用了CTempValue的构造函数创建了一个临时对象,因为CTempValue构造函数的两个参数都有默认值,所以这里的数字1000就顶替了第一个参数,而第二个参数系统就用了默认值,所以从1000是可以成功创建出CTempValue对象的。

为了进一步观察,增加拷贝赋值运算符的代码:

CTempValue& operator=(const CTempValue& tmpv)
{
	cout << "调用了拷贝赋值运算符" << endl;
	val1 = tmpv.val1;
	val2 = tmpv.val2;
	cout << "val1 = " << val1 << endl;
    cout << "val2 = " << val2 << endl;
	return *this;
}

执行程序,看下结果:

调用构造函数
val1 = 0
val2 = 0
调用构造函数
val1 = 1000
val2 = 0
调用了拷贝赋值运算符
val1 = 1000
val2 = 0
调用了析构函数
调用了析构函数

总结sum = 1000;这行代码系统做了哪些事:

用1000这个数字创建了一个类型为CTempValue的临时对象;调用拷贝赋值运算符把这个临时对象里面的各个成员值赋给了sum对象;销毁这个刚刚创建的CTempValue临时对象。

那如何优化呢?

可以把main主函数中刚刚写的两行代码优化成下面一行:

CTempValue sum = 1000; //" = " 在这里不是赋值运算符,而是定义初始化的概念

运行结果如下:

调用构造函数
val1 = 1000
val2 = 0
调用了析构函数

可以看到,系统没有生成临时对象,所以系统少调用了一次构造函数,少调用了一次拷贝赋值运算符、少调用了一次析构函数。

1.2.2 隐式类型转换以保证函数调用成功

int calc(const string& strsource, char ch)
{
	const char * p = strsource.c_str();
	int icount = 0;
	//......具体的统计代码
	return icount;
}
//在main主函数的代码如下:
int main()
{
	char mystr[100] = "I love China, oh, yeah!";
	int result = calc(mystr, 'o');
	return 0;
}

一个是char数组,一个是const string&,但是这个函数就能调用成功,为什么呢?

当然是编译器帮助我们做了一些事情,解决类型不匹配,那是如何做的呢?

那就是编译器产生了一个类型sring的临时对象,这个临时对象的构造方式就是用mystr作为参数,调用了string的构造函数,这样形参strsoutce就绑定到这个string临时对象上了。当calc函数返回的时候,这个临时对象会被自动销毁。

C++只会为const string&(const引用)产生临时对象,不会为string&(非const)产生临时对象。

1.4 函数返回值的时候 - 如何优化呢?

我们在main主函数上面加一个普通的全局函数:

CTempValue Double(CTempValue& ts)
{
	CTempValue tmpm;	//这里会消耗一次构造函数和一次析构函数的调用
	tmpm.val1 = ts.val1 * 2;
	tmpm.val2 = ts.val2 * 2;
	return tmpm; //这里会调用构造函数和析构函数,这表示生成了一个临时对象
}

int main()
{
	CTempValue ts1(10, 20);
	CTempValue ts2 = Double(ts1);  //其实临时对象接管的就是右值
	CTempValue&& ts2 = Double(ts1);  
}

临时对象就是一种右值

那如何优化呢?

CTempValue Double(CTempValue& ts)
{
	return CTempValue(ts.val1 * 2, ts.val2 * 2); 
}

通过如上的优化系统会调用一次拷贝构造函数,一次析构函数。

二、小结

(1)写代码的时候,减少临时变量的产生。
(2)锻炼眼神,能够尽量看出哪些地方可能会产生临时对象,尤其是一个函数只要返回一个对象,一般机会产生临时对象。

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

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

相关文章

Ubuntu设置虚拟机共享目录/mnt/hgfs下无文件显示相关问题归纳

文章目录 问题一&#xff1a;/mnt目录下无hgfs文件夹问题二&#xff1a;/mnt/hgfs 文件夹为空 问题一&#xff1a;/mnt目录下无hgfs文件夹 问题背景&#xff1a; 在打开共享目录A的时候&#xff0c;突然改变共享目录&#xff0c;也就是从A改到了B&#xff0c;但是资源管理器还…

TiDB v7.1.0版本 相关(部署、在线扩容、数据迁移)测试

作者&#xff1a; tomxu 原文来源&#xff1a; https://tidb.net/blog/69083bca TiDB v7.1.0版本 相关&#xff08;部署、在线扩容、数据迁移&#xff09;测试 一、服务器信息参数 | 序号 | 服务器型号 | 主机名 | 配置 | | IP地址 | 用户名 | 密码 | | -- | --------- | …

chatgpt赋能python:Python怎么过滤异常值-降噪数据的利器

Python怎么过滤异常值 - 降噪数据的利器 什么是异常值 在数据分析和机器学习领域&#xff0c;我们常常需要对数据进行预处理&#xff0c;其中一个常见的问题就是异常值。也可以称为噪声数据或离群点&#xff0c;指数据集中与其他值相差较大的点。通常这些异常值出现的原因有很…

6.10 面向对象抽象

抽象类 1 概念 Java中可以定义被abstract关键字修饰的方法,这种方法只有声明,没有方法体,叫做抽象方法. Java中可以定义被abstract关键字修饰的类,被abstract关键字修饰的类叫做抽象类 如果一个类含有抽象方法,那么它一定是抽象类 抽象类中的方法实现交给子类来完成 2 抽象…

MsSqlServer配置管理器TCP/IP属性

TCP/IP 属性&#xff08;“IP 地址”选项卡&#xff09; 使用 “TCP/IP 属性&#xff08;‘IP 地址’选项卡&#xff09;” 对话框&#xff0c;可以配置特定 IP 地址的 TCP/IP 协议选项。 只有选中 “IP All” &#xff0c;才能一次配置所有地址的 “TCP 动态端口” 和 “TCP…

Linux学习[16]bash学习深入2---别名设置alias---history指令---环境配置相关

文章目录 前言1. alias2. history3. 环境配置相关总结 前言 linux学习15里面简单提了一下alias指令&#xff0c;就表明它是一个别名的作用&#xff0c;这节就展开来写一下。 同时上一节一笔带过的history指令&#xff0c;这一节也进行例子的演示记录。 最后是环境相关的配置&a…

高斯过程(Gaussian Process)回归预测,例子,代码及可视化展示

高斯过程指的是一组随机变量的集合&#xff0c;这个集合里面的任意有限个随机变量都服从联合正态分布。&#xff08;联合正态分布是指多个随机变量的联合分布满足正态分布。联合分布是指多个随机变量同时满足的概率分布&#xff0c;一个常见的例子是考虑两个随机变量&#xff1…

【2023年最新】提高分类模型指标的六大方案详解

文章目录 数据增强特征选择调整模型参数模型集成迁移学习模型解释完结 当今&#xff0c;机器学习模型得到了广泛的应用&#xff0c;其中分类模型是其中最常见和重要的一种。在实际应用中&#xff0c;如何提高分类模型的指标&#xff0c;使其在不同场景下表现更佳并且具有更好的…

【Web网页制作】影视主题网页制作web页面开发(附源码)

【写在前面】 其实之前我就写过一篇关于我的家乡的页面&#xff0c;也有不少网友和我私下反馈&#xff0c;让我多出一些关于页面制作的&#xff0c;于是乎我就今天晚上抽出点时间来整理一篇关于影视内容的web页面制作&#xff0c;希望能够得到大家的喜欢。 【涉及内容】 web网页…

什么是进程?程序又是什么?程序运行在操作系统来看是怎么做的?

相信很多人都看到过课本上写的进程的概念&#xff0c;那么真的理解了吗&#xff1f; 课本上是这样讲的&#xff0c;课本概念&#xff1a;程序的一个执行实例&#xff0c;正在执行的程序等。 那么进程到底是什么&#xff1f;我先把内核层面上的概念拿出来&#xff1a;内核观点&a…

【算法基础】基础算法

快速排序 模板题&#xff1a;785. 快速排序 - AcWing题库 思路&#xff1a; 定义一个x&#xff08;一般喜欢用中间的&#xff09;&#xff0c;我们快速排序&#xff0c;让x左边的都比它小&#xff0c;同时让右边的都比它大。然后像二分一样不断细分&#xff0c;缩小范围进行同…

flink主要组件及高可用配置

背景 flink不论运行在哪种环境&#xff0c;例如Yarn&#xff0c;Mesos&#xff0c;Kebernute以及独立集群&#xff0c;每个应用都会包含重要的几个组件&#xff0c;本文就来讲述下flink的主要组件以及如何实现flink的高可用配置 flink主要组件 如图所示&#xff0c;flink主要…

TiDB 7.1 资源管控特性试用

作者&#xff1a; 啦啦啦啦啦 原文来源&#xff1a; https://tidb.net/blog/3ddb423a 一.背景 印象里 2022 年初的时候就有小伙伴在 asktug 提出 TiDB 未来是否会有多租户功能的问题了&#xff0c;没想到这么快就已经 GA 了。资源管控特性&#xff08;Resource Control&…

【论文阅读】Weighted Boxes Fusion(WBF)模型融合原理解读

论文地址&#xff1a;https://arxiv.org/pdf/1910.13302.pdf 代码地址&#xff1a;GitHub - ZFTurbo/Weighted-Boxes-Fusion: Set of methods to ensemble boxes from different object detection models, including implementation of "Weighted boxes fusion (WBF)"…

chatgpt赋能python:Python中如何转化大小写

Python中如何转化大小写 在Python编程中&#xff0c;转化字符串的大小写是一个常见的操作。Python提供了内置函数和字符串方法来实现此操作。本文将介绍如何使用Python中的这些函数和方法来转换字符串的大小写。 使用内置函数str.upper()和str.lower() str.upper()函数将字符…

共创开源生态 | 小米肖翔荣获“2023中国开源优秀人物”奖

6月15-16日&#xff0c;以“开源创新 数字化转型 智能化重构”为主题的“第十八届开源中国&#xff65;开源世界高峰论坛”在北京成功召开。小米工程师肖翔凭借其在 Apache 基金会的开源贡献及在操作系统领域内的技术突破&#xff0c;荣获“2023中国开源优秀人物”奖。 Xiaomi …

一文读懂候选边界框Selective Search、AnchorBased、Anchor Free

目标检测是计算机视觉中的一项重要任务&#xff0c;主要目的是在图像或视频中识别并定位感兴趣的对象。为了实现这一目标&#xff0c;目标检测算法通常会生成一系列候选边界框&#xff0c;这些框包围了图像中可能存在的目标对象。候选边界框技术对于减少目标检测的计算复杂度和…

Vue中的数据可视化词云展示与词云生成

Vue中的数据可视化词云展示与词云生成 数据可视化是现代Web应用程序中的一个重要组成部分&#xff0c;它使得数据更加易于理解和分析。词云是一种非常流行的数据可视化形式&#xff0c;它可以用来展示文本数据中的主题和关键字。在本文中&#xff0c;我们将介绍如何在Vue中使用…

chatgpt赋能python:Python怎么转化数据类型?

Python怎么转化数据类型&#xff1f; Python是一种高级编程语言&#xff0c;它已经成为了许多程序员的首选语言。在Python中&#xff0c;数据类型是非常重要的一部分。但是&#xff0c;当我们需要将数据从一种类型转换为另一种类型时&#xff0c;该怎么做呢&#xff1f;在本文…

深度学习:探索人工智能的新前沿

第一章&#xff1a;引言 人工智能&#xff08;Artificial Intelligence&#xff0c;AI&#xff09;作为一项前沿技术&#xff0c;在近年来取得了巨大的进展。其中&#xff0c;深度学习&#xff08;Deep Learning&#xff09;作为人工智能领域的一个重要分支&#xff0c;更是引…