点击蓝色“
五分钟学算法
”关注我哟
加个“
星标
”,天天中午 12:15,一起学算法
作者 |
守望先生
来源 |
编程珠玑
前言
不知道你是否听说过 ++i 比 i++ 快的说法,真的如此吗?
++i与i++的区别
这两个表达式从我们初学编程语言的时候就会接触到。
前者是自增后取值,后者是取值后自增
。
我们看一个简单的例子。
#include
using namespace std;
int main()
{
int a = 0;
int b = 0;
int c = a++;
int d = ++b;
cout<<"c="<";d="<endl;
return 0;
}
运行结果:
c=0;d=1
对于这个结果我们并不感到意外。
另外我们还注意到另外一个有意思的现象:
#include
using namespace std;
int main()
{
int a = 0;
int b = 0;
int *c = &(a++);
int *d = &(++b);
return 0;
}
编译后报错:
main.cpp:7:19: error: lvalue required as unary ‘&’ operand
int *c = &(a++);
说&作用于左值,也就是说a++的结果并非左值。但++b的结果是左值。
可简单理解左值和右值:
-
左值,有名对象,可赋值
-
右值,临时对象,不可被赋值
运算符重载
在《
运算符重载
》一文中已经说到了运算符的重载,通过前面的例子也发现了,对于内置类型,前置自增返回对象的引用,而后置自增返回对象的原值(但非左值)。
基于上述原则,一个前置版本和后置版本的常见实现如下:
class Test
{
public:
Test& operator++();
const Test operator++(int);
private:
int curPos;
};
Test& Test::operator++()
{
++curPos;
return *this;
}
const Test Test::operator++(int)
{
Test tmp = *this;
++curPos;
return tmp;
}
仔细观察后,我们发现前置自增,先自增,后返回原对象的对象;没有产生任何临时对象;而后置自增,先保存原对象,然后自增,最后返回该原临时对象,那么它就需要创建和销毁,这样一来,效率孰高孰低就很清楚了。
在不进行赋值的情况下,内置类型前置和后置自增的汇编都是一样的呢!
void