专栏首页编程珠玑为什么说++i的效率比i++高?

为什么说++i的效率比i++高?

来源:公众号【编程珠玑】

作者:守望先生

网站:https://www.yanbinghu.com

前言

不知道你是否听说过++i比i++快的说法,真的如此吗?

++i与i++的区别

这两个表达式从我们初学编程语言的时候就会接触到。前者是自增后取值,后者是取值后自增。 我们看一个简单的例子。

#include <iostream>
using namespace std;
int main()
{
    int a = 0;
    int b = 0;
    int c = a++;//int tmp = a;c=a;a = a + 1
    int d = ++b;//b = b + 1;d = b;
    cout<<"c="<<c<<";d="<<d<<endl;
    return 0;
}

运行结果:

c=0;d=1  

对于这个结果我们并不感到意外。

另外我们还注意到另外一个有意思的现象:

//来源:公众号【编程珠玑】地址:https://www.yanbinghu.com
#include <iostream>
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的结果是左值。

可简单理解左值和右值:

  • 左值,有名对象,可赋值
  • 右值,临时对象,不可被赋值

运算符重载

在《运算符重载》一文中已经说到了运算符的重载,通过前面的例子也发现了,对于内置类型,前置自增返回对象的引用,而后置自增返回对象的原值(但非左值)。 基于上述原则,一个前置版本和后置版本的常见实现如下:

//来源:公众号【编程珠玑】地址:https://www.yanbinghu.com
class Test
{
public:
    Test& operator++();//前置自增
    const Test operator++(int);//后置自增
private:
    int curPos; //当前位置
};
/*前置自增实现范式*/
Test& Test::operator++()
{
    ++curPos;      //自增
    return *this;  //取值
}
/*后置自增实现范式,为了与前置区分开,多了一个int参数,但从来没用过*/
const Test Test::operator++(int)
{
    Test tmp = *this;  //取值
    ++curPos;             //自增
    return tmp;
}

仔细观察后,我们发现前置自增,先自增,后返回原对象的对象;没有产生任何临时对象;而后置自增,先保存原对象,然后自增,最后返回该原临时对象,那么它就需要创建和销毁,这样一来,效率孰高孰低就很清楚了。

在不进行赋值的情况下,内置类型前置和后置自增的汇编都是一样的呢!

void test()
{
  int i = 0;
  i++;
  //++i;
}

汇编:

push    rbp
mov     rbp, rsp
mov     DWORD PTR [rbp-4], 0
add     DWORD PTR [rbp-4], 1
nop
pop     rbp
ret

不过,赋值的情况下,并且不开启编译器优化,它们的汇编代码还是有差别的,有兴趣的可以试试。

总结

对于内置类型,前置和后置自增或者自减在编译器优化的情况下,两者并无多大差别,而对于自定义类型,如无特别需要,人们似乎更加偏爱前置自增或自减,因为后置自增常常会产生临时对象。

但是,又能提高多少效率呢?

本文分享自微信公众号 - 编程珠玑(shouwangxiansheng),作者:守望先生

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-09-11

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 几个无聊但你可能忽略的C知识点

    注意,使用函数前一定要声明,对于没有声明,而试图使用,可能会错将int用成其他类型,导致灾难。参考《记64位地址截断引发的挂死问题》

    编程珠玑
  • 你见过数组的这种骚操作吗?

    注意看printf那一行,发现什么了没有?竟然有i[a]这样的操作?然后你运行一下还会发现,结果完全正常。

    编程珠玑
  • decltype--从表达式推断类型

    在《不想写表达式的类型?试试auto吧》中介绍了自动类型推导,它需要有初始值,今天再来介绍一个C++11中的特性,decltype。

    编程珠玑
  • 五分钟小知识:为什么说 ++i 的效率比 i++ 高?

    这两个表达式从我们初学编程语言的时候就会接触到。前者是自增后取值,后者是取值后自增。 我们看一个简单的例子。

    五分钟学算法
  • 为什么说++i的效率比i++高?

    这两个表达式从我们初学编程语言的时候就会接触到。前者是自增后取值,后者是取值后自增。 我们看一个简单的例子。

    帅地
  • 开发 | 训练一个AI给颜值打分,公平公正!

    AI 科技评论按:本文作者灰灰,本文原载于作者的知乎专栏。授权转载。 机器学习是不是很无聊,用来用去都是识别字体。能不能帮我找到颜值高的妹子,顺便提高一下姿势水...

    AI科技评论
  • 让AI给颜值打分?应该是最公正的裁判了!

    机器学习是不是很无聊,用来用去都是识别字体。能不能帮我找到颜值高的妹子,顺便提高一下姿势水平。 FaceRank 基于 TensorFlow CNN 模型,提供...

    AI研习社
  • 5970 格子游戏

    题目描述 Description Alice和Bob玩了一个古老的游戏:首先画一个n * n的点阵(下图n = 3)   接着,他们两个轮流在相邻的点之间画上红...

    attack
  • 上个版本我就改了一行代码!

    用户1907613
  • Android一 流

    补充Java知识:流 java.io 四个抽象类: 字节流:InputStream OutputStream 字符流:Reader Writer 站在程序角度上...

    小端

扫码关注云+社区

领取腾讯云代金券