zoukankan      html  css  js  c++  java
  • i++ and ++i efficiency

    其实这个问题,百度的话,有一大堆的参考资料,但是,在这里,我产生了一些困惑,他们所分析的结果,和我的测试代码不一致,这让我纠结了,所以,再次的写一下这个问题,顺顺思路。


    我的测试环境:系统:Windows7 32bit,编程平台:Qt 5.3.1 (MSVC 2010,32bit)

    首先说一下比较被大众所认可的结果:

    (1)在自定义的数据类型的时候,因为前缀式(++i)可以返回对象的引用,而后缀式(i++),必须返回对象的数值,所以,导致在大的对象的时候产生了较大的复制开销,引起效率降低。所以,使用自定义的数据类型的时候,使用前缀式(++i)效率更好一些;

    (2)如果是内置类型的,如int,效率是一样的。

    (3)c++Primer上面有说:对于老旧的编译器++i效率好,对于好的编译器i++被优化了(效率一样)。表示该用哪个用哪个。


    我的测试代码

    #include <iostream>
    using namespace std;
    //struct(1 data member)
    struct oj
    {
        int j;
    }a;
    
    //(2 data members) class
    class oo
    {
    public:
        oo():a(0),b(0){}
        oo operator ++()//Prefix plus
        {
            ++a;
            ++b;
            return *this;
        }
        oo operator ++(int)//suffix plus
        {
            oo temp(*this);
            a++;
            b++;
            return temp;
        }
    private:
        int a;
        int b;
    };
    int main()
    {
        int i=0;
        int x=0;
        //Built-in data types
        i++;
        ++i;
        x=i++;
        x=++i;
    
        //struct(1 data member)
        a.j = 0;
        a.i = 0;
        a.j++;
        ++a.j;
        x = a.j++;
        x = ++a.j;
    
        //(2 data members) class
        oo o,ox;
        o++;
        ++o;
        ox = o++;
        ox = ++o;
        return 0;
    }

    最接近机器语言的汇编

    (1)先分析内建的数据类型

    Image 1

    分析结果如下:

    对于内建的数据类型,单独使用i++和++i是没有效率区分的。但是,表达式中的i++和++i是有区别的,如上图所示,所以对于内建的表达式中的,根据需求,含有++i的表达式的效率要好一些。(注意,这里我强调的是整个表达式的效率。而非单纯的i++ and ++i.)


    (2)自定义的数据类型(结构体)

    如测试代码,这里使用了结构体,包含一个数据成员。

    Image 2

    分析结果如下:

    对于一个结构体(包含有一个数据成员)的自定义数据类型而言,单独的a.j++ and ++ a.j的效率是一样的,没有什么可争论的。但是,对于表达式的中的 x = a.j++ and x = ++a.j,这个表达式的效率,结果确出现了和“自定义的数据类型中,++i的效率更好”的违背。原因图片中已经解释过了,所以,对于表达式中含有自增和自减运算符的,在讨论表达式的效率的时候,不能单纯的使用理论依据,还应该考虑自己的平台环境,编译器的指令集系统,这里我想到了精简指令集和复杂指令集。


    (3)自定义数据类型(类,2个数据成员,重载++运算符)

    Image 3

    分析结果:

    对于类对象的自增运算,我们重载了运算符。从汇编代码来看,不管是单独使用,还是含有自增运算符的表达式,O++操作,因为有入栈和出栈操作,所以,显得效率有些不佳。但是,在这里,我们完全没有考虑重载函数的运行效率,这里只是显示了函数的调用。其实,这里不用深究重载函数的效率了,单从C++语言就可以看出来。前缀的++i的重载函数的效率更好一些。

    2个重载函数的汇编代码对比(左边为++i前缀的重载,右边为i++后缀的重载):

    Image 5


    自我总结

    这里,我不想说,i++ 和 ++i的效率哪一个更好,通过上面的测试代码,我们可以发现,对于不同的环境,不同的数据结构会有不同的效率。我想说的是,通过发现一个问题,然后寻找答案,质疑答案,验证答案的这个过程,让我学会了不少东西。也许我的验证方法是不科学的,但是从中我认真的对待过,从中,学会了阅读汇编代码,这使我更加深刻的理解了机器对于程序的运行机制是什么样的。认真对待问题,你会从中收获很多的。

    如果有面试官问你这样的问题的话,可以如下回答:

    内建的数据类型时,效率一样。
    但是,在自定义的数据类型的时候,因为前缀式(++i)可以返回对象的引用,而后缀式(i++),必须返回对象的数值
    所以,导致在大的对象的时候产生了较大的复制开销,引起效率降低。
    所以,使用自定义的数据类型的时候,使用前缀式(++i);

    同时,真的需要在细节上提高自己程序效率的话,你可以写个简单的测试用例,测试一下。因为在自己的平台上测试,相对准确一些。没必要,像我这么纠结。

  • 相关阅读:
    JAVA核心技术笔记总结--第14章 线程总结
    java核心技术笔记——第 9 章 集合
    Java核心技术笔记——第 8 章 泛型
    2.面向对象三大特征
    1.浅谈面向对象思想
    8.字符串
    7.数组
    6.调试程序
    5.流程控制语句
    4.运算符
  • 原文地址:https://www.cnblogs.com/zi-xing/p/4456264.html
Copyright © 2011-2022 走看看