i++ 与 ++i 的效率哪个更高?

来源:互联网 发布:淘宝如何实名制认证 编辑:程序博客网 时间:2024/04/30 20:31

1、http://hi.baidu.com/keeptry/item/851a943815af4049033edc95

2、http://bbs.csdn.net/topics/250027391


很多C语言的书上都对i++与++i运算的区别问题进行了说明,但很多人只是强行记住了二者的区别,而未对其进行深入的思考。我也是如此,所以今天我尝试对这个问题进行一下更深入的学习。

下面我将从i++与++i运算的运行结果和运行效率方面对此问题进行说明。

(一)运行结果

i++ :先进行运算,再执行i = i +1的操作;
++i :先执行i = i +1的操作,再进行运算;

例1:赋值
int x=y=0;
y = x++; //执行后y的值仍为 0;

int x=y=0;
y = ++x; //执行后y的值则为 1;

例2:条件判断
int x=0;
if( x++ == 1) //条件为假
{
}

int x = 0;
if( ++x == 1) //条件为真
{
}

例3:在for循环中++i跟i++有区别吗?

没有区别,for(;;)第2个分号后面的语句是在每次循环结束后执行的,相当于一个独立的语句。
for (int i = 0; i < 1024; i++) 
{
    a = 0; 
}
相当于 
for (int i = 0; i < 1024; ) 

    a = 0; 
    i++;    
}

for (int i = 0; i < 1024; ++i) 
{
    a = 0; 
}
相当于 
for (int i = 0; i < 1024; ) 

    a = 0; 
    ++i;  
}

在这里,因为i++与++i等效,因此没有区别。

(二)运行效率

这是很多人在论坛里面讨论过的问题,一般来说,我们不用太关注这个问题,但如果大家有兴趣的话可以继续读下去。

下面是一篇关于 i++ 和 ++i 在C++中的效率问题的文章,此帖对二者的处理情况来对该问题进行了很好的说明。由于C代码通常也是使用C++的编译器来进行编译的,因此下文对C编程也同样适用。

注:以下内容转载于http://web4.idcdns.cn/blog/article.php?tid-501.html
----------------------------------------
单独的一句 i++ 或 ++i 作用是一样的,不少书上都说推荐写成 ++i 的形式,却从来没说明道理。 
为什么要推荐写成 ++i 呢? 
i++; // 有一个临时变量 
++i; // 无临时变量 


//////////////////////////////////////////////////////////////////// 

for ( int i = 0; i < 100; i++ )    
{    
       /* ………… */    



但是很少有人想过代码背后隐藏的问题。读过STL源代码的人,都会对下面的代码一定很熟悉。    


template<class _II, class _OI> inline    
_OI copy( _II _F, _II _L, _OI _X )    
{    
       for ( ; _F != _L; ++_X, ++_F )    
               *_X = *_F;    
       return (_X);    
}    
// 摘自Visual C++ 6.0 STL实现,文件:xutility。    

   

为什么它不写成    


template<class _II, class _OI> inline    
_OI copy( _II _F, _II _L, _OI _X )    
{for ( ; _F != _L; _X++, _F++ )    
       *_X = *_F;    
       return (_X);    



看完这篇文章,你就可以知道这样写的理由。    

C++是一种非常强大的语言,它赋予了它的使用者和他的创建者相同的权力。每一个内在的数据类型所支持的操作,你几乎都可以为自己定义的类型实现。运算符重载是其中的重要组成部分。    

对于一个类CInt的运算符(这里只讨论加法),我们一般会这样实现:    


class CInt    
{    
public:    
       CInt& operator ++();    
       CInt operator ++( int );    
       CInt& operator +=( const CInt& that );    
};    

CInt operator +( const CInt& this, const CInt& that ); 


其中,CInt& operator ++();对应于++i;(如果i是CInt的一个实例,下同)返回引用的原因是因为在C++里,++i的结果应该是一个左值。对这个函数的调用,除了运算本身以外,并没有什么开销。(除了隐含的this以外,无传递参数,只有一个引用返回值,所以没有新的实例被创建)    
CInt operator ++( int ); 对应于i++;那个int是无意义的,只是为了把前缀运算和后缀运算区分开。返回变量(而不是引用)的原因是因为在C++里,i++的结果应该是一个右值,并且是i在没有加之前的值(所以不能返回它的const引用)。在这个函数中,会创建一个临时变量,并把它作为返回值拷贝给调用者。    
CInt& operator +=( const CInt& that );对应于i = i + j;传递一个参数,从理论上来说,它的开销和++I的开销是一样的,但是,如果你只是要对类的实例加一的话,应该用++I,因为那个函数可能为加一而特别优化过。(具体可以参见实例)    
CInt operator +( const CInt& this, const CInt& that );对应于k = i + j;这个函数的开销与i++相同,但是要注意的是,i++可能为加一而优化的。    

为了能够显著的测出各个函数的具体效率,我使用了一个非常"大"的类,CVector,一个65536维的整型向量。测试结果为:    

Another += One : 4326    
Another++ : 9274    
Another = Another + One : 9223    
++Another : 2153    

可以看出,同样是加一,++i可以比i++快很多。    

当然,编译器的优化也很重要,在某些情况下,编译器可以将i++的速度优化到和++i一样。但是,为什么不直接写出++i呢?这样可以保证在任何情况下都能获得较快的执行速度,而不是去依赖于编译器的优化。(至少,Visual C++ 6.0是不支持的)



-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------




原创粉丝点击