c++性能优化:临时对象

  • 前言

对于性能来说,实际上许多的问题都需要和出现的频率以及本身执行一次的开销挂钩,有些问题虽然看似比较开销较大,但是很少会执行到,那么也不会对程序有着非常大的影响;同样的一个很小的开销的函数执行很频繁,同样会对程序的执行效率有很大的影响。这一章中作者主要是根据临时对象来阐述这样一个观点。

  • 对象定义

先看下文章中提到的例子:

class Rational
{
friend Rational operator + (const Rotional& a, const Rotional& b);
public:
    Rotional (int a = 0, int b = 0):m(a),n(b){}
private:
    int m;
    int n;
};

// 初始化方法
Rotional r1(100);
Rotional r3 = Rotional(100);
Rotional r3 = 100;

上面写的三种初始化Rotional的方法只有第一种在最终执行的过程中不会产生临时的对象,其他两种方式根据编译器的实现不同,都有可能产生临时对象。

  • 类型不匹配

上面例子中的第三种实际上是常见的类型不匹配的情况,因此需要编译器在构造的过程中现将整型转换成Rotional的形式。在这个过程中就有可能会产生临时的对象。文中还将编译器可能进行的转换步骤进行了说明,如下:

// 原本形式
Rotional r = 100;

// 编译器在编译时会改变现有的表达式,转换成如下的形式
Rotional _temp;
_temp.Rotional::Rotional(100, 0);
r. Rotional::operator = (_temp);
_temp.Rotional::~Rotional();

虽然上面这种方式看似会直接解决类型不匹配的问题,但是现在新的c++语法加入了explicit关键字,用处就是强制使用自己定义的构造函数,默认的构造函数就不会存在。如果构造函数明确使用了该关键字,那么如果还想实现类型转换就需要自己写operator=的构造函数。并且自己申明函数的话也可以实现临时对象的减少。

Rotioanl& operator = (int a)
{
    m = a;
    n = 0;
    return *this;
}

类型的不匹配经常会造成类似的临时对象的创建,如下:

void g(const string& s)
{
    ...
}

上面的这个函数接受的是string类型的参数,如果传入一个char*的类型,就会产生一个string类型的临时对象,同样的情况也会在下面的函数中产生

Complex a,b;
for (int i = 0; i < 100; i++)
{
    a = i * b + 1.0;
}

上述的函数在100次循环的过程中,正常都会执行100次的1.0 double 型转换为Complex的内部转换,这样的转换是可以避免的,最简单的方法就是先申明好,Complex one(1.0),这样的话每次都是用的是Complex类型的数据进行计算。

  • 按值传递

按值传递相信大家在学习基础的函数语法时都遇到过,编译器会在调用的时候创建一个临时的对象,并拷贝构造,这个创建出的临时对象再当作实参传递给函数。但是临时创建对象以及清除对象的开销是比较大的,一般比较推荐的做法就是指针以及引用的方式。

  • 按值返回

另一个会导致临时对象创建的地方就是按值返回,原理其实我觉得和形参产生临时对象的原理是相似的,解决的方式也大都是使用引用的方式解决。

  • 使用op=的方式解决临时对象

之前类型不匹配的时候提到,为了防止匹配类型产生临时对象的开销,我们一般会自己先构建一个该类型的对象。那么相似的原理也可以用在这个上面。比如:

string s1,s2,s3;
s3=s1+s2;

为了达到极致的性能优化,一般可以重栽=和+=,

s3 = s1;
s3 += s2;

这样在实现重载之后执行这样的步骤就可以减少临时对象的创建,虽然这样的计算看似多此一举,但是对于性能要求很高的程序来说就需要舍弃一些程序的优雅性。

  • 要点

临时对象会以构造函数和析构函数的方式损失两倍的性能。

把构造函数申明为explicit,可以阻止编译器在背后使用类型转换。

编译器经常会为了解决类型不匹配问题创建临时对象,通过函数重载可以解决这一问题

在函数传参以及返回值的定义中,尽量使用引用的方式

在可能是+、-、*、/的情况下使用=可以消除临时对象

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
性能优化指南是指在软件或系统开发过程中,通过一系列的优化措施来提升程序的执行效率和系统的性能表现。这样可以使得软件和系统更加高效地运行,提供更好的用户体验。 性能优化的目标在于减少程序的资源消耗、提高响应速度和降低延迟。为了达到这些目标,我们可以从多个方面入手: 1. 代码优化:通过优化算法、减少冗余代码、精简逻辑等方式,改善代码的执行效率。同时,要避免频繁的内存分配和释放操作,使用更高效的数据结构和算法。 2. 并发优化:对于一些多线程或并行计算的场景,可以采用合适的并发模型和数据共享机制,避免竞争条件和死锁,提高并发性能。 3. 数据库优化:优化数据库的设计和索引,合理使用查询语句和事务,避免频繁的数据库访问和大量的数据传输,提高数据库的读写效率。 4. 网络优化:优化网络通信协议和数据传输方式,减少数据传输量和网络延迟,提高网络通信的效率。 5. 缓存优化:通过合理设置缓存机制,减少重复计算和数据查询的开销,提高系统的响应速度。 6. 资源管理优化:合理管理系统资源,及时释放未使用的资源,减少资源的浪费。 7. 日志优化:精简和优化日志输出,避免不必要的日志记录,减轻系统负担。 8. 前端优化:优化前端页面的加载速度和渲染性能,减少页面的请求次数和数据量,提高用户体验。 综上所述,性能优化是一个综合性的工作,要从代码、并发、数据库、网络、缓存、资源管理、日志和前端等多个方面入手。通过适当的优化策略和手段,可以提升软件和系统的性能表现。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值