C++中自加(i++/++i)自减(i--/--i)运算符效率分析

结论:优先使用 ++i 和 --i 以提高运行效率

虽然大家都知道 i++/i-- 是先使用再自加减,而 ++i/--i 则是先自加减再使用

首先回顾下:

C++中自加自减运算符的重载

自增运算符++、自减运算符--都可以被重载,但是它们有前置、后置之分。

++为例,假设 obj 是一个 CDemo 类的对象,++objobj++本应该是不一样的,前者的返回值应该是 obj 被修改后的值,而后者的返回值应该是 obj 被修改前的值。如果如下重载++运算符:

CDemo & CDemo::operator ++ ()
{
    //...
    return * this;
}

那么不论obj++还是++obj,都等价于obj.operator++()无法体现出差别。

为了解决这个问题,C++ 规定,在重载++--时,允许写一个增加了无用 int 类型形参的版本,编译器处理++--前置的表达式时,调用参数个数正常的重载函数;处理后置表达式时,调用多出一个参数的重载函数。来看下面的例子:

#include <iostream>
#include <vector>
using namespace std;

class MyInt
{
public:
	MyInt(int i = 0) { n = i; }
	MyInt & operator++();//前置++,++i
	MyInt operator++ (int);//后置++,i++

	//友元函数形式的函数重载
	friend MyInt & operator --(MyInt &);//前置--,--i
	friend MyInt operator --(MyInt &, int);//后置--,i--

	friend ostream & operator<<(ostream &out, MyInt in); //重载输出运算符
	//或者重载int运算符
	operator int() { 
		cout << "重载了 << 运算符" << endl;
		return n; 
	}


private:
	int n;
};


MyInt & MyInt::operator++()
{
	n = n + 1;
	return *this;
}

MyInt MyInt::operator++(int)
{
	//需要创建一个临时对象,保存之前的数据,然后再自加
	MyInt temp(*this);
	n = n + 1;
	return temp;
}

MyInt & operator--(MyInt &i)
{
	i.n = i.n - 1;
	return i;
	
}
MyInt operator --(MyInt &i, int){
	MyInt temp(i);//这里使用了默认拷贝构造函数
	i.n = i.n - 1;
	return temp;
}
ostream & operator<<(ostream &out, MyInt in)
{
	cout << "重载了 << 运算符" << endl;
	out << in.n;
	return out;
}


int main(void) {

	MyInt i(666);
	cout << "i = "<< i++ << endl;
	cout << "i = " << ++i << endl;
	cout << "i = " << i-- << endl;
	cout << "i = " << --i << endl;

	return 0;
}
/*
 *
 *
i = 重载了 << 运算符
666
i = 重载了 << 运算符
668
i = 重载了 << 运算符
668
i = 重载了 << 运算符
666*/

再回到自加自减的源码实现:

// 前置自加自减
// ++i
T& T::operator++(){       
    ++*this;             
    return *this;       
}

// --i
T& T::operator--(){
    --*this;
    return *this;
}
//后置自加自减
T T::operator++(int){                   
    T old(*this);                           
    ++*this;                               
    return old;                             
}                                       

T T::operator--(int){
    T old(*this);
     --*this;
    return old;
}

自增自减的后缀形式所多花费的开销:
    T old(*this);
这一句产生一个类型为T的临时对象 old, 并用原值*this进行初始化.当函数return的时候,又再次创建一个临时对象,并用old的值进行初始,之后,局部变量old被销毁.并用临时创建的变量对赋值符左边的变量进行赋值(如果有的话).赋值后,临时变量再次被销毁.
而前缀形式的自增自减呢?

首先函数内没有创建临时变量,故这方面的开销就节省了。其次,返回的是一个引用。故也节省了这时候创建销毁临时对象的开销.。

因此后缀式的自增自减,所多花费的开销是两次临时变量的创建,以及两次临时变量的销毁,如果自增自减的对象不是内建的数据类型,而一个类类型[当然,你首先得重载自增自减操作符, 那么这个开销可能会比较大,因为变成了两次构造函数以及两次析构函数的调用。
    所以在调用代码的时候,要优先使用前缀形式,除非确实需要后缀形式返回原值。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SOC罗三炮

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值