﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-精灵乐园-文章分类-C++</title><link>http://www.cppblog.com/jlthero/category/9719.html</link><description>精灵世界的王子</description><language>zh-cn</language><lastBuildDate>Tue, 10 Mar 2009 20:01:08 GMT</lastBuildDate><pubDate>Tue, 10 Mar 2009 20:01:08 GMT</pubDate><ttl>60</ttl><item><title>++i 和 i++执行效率的问题(ZZ)</title><link>http://www.cppblog.com/jlthero/articles/75553.html</link><dc:creator>精灵童</dc:creator><author>精灵童</author><pubDate>Wed, 04 Mar 2009 14:12:00 GMT</pubDate><guid>http://www.cppblog.com/jlthero/articles/75553.html</guid><wfw:comment>http://www.cppblog.com/jlthero/comments/75553.html</wfw:comment><comments>http://www.cppblog.com/jlthero/articles/75553.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/jlthero/comments/commentRss/75553.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jlthero/services/trackbacks/75553.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 这个问题是去深圳港湾公司面试的 时候面试官问的。当时一头雾水，从来没有想过这其中还会有区别。殊不知，这区别可大了！
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 单独的一句 &nbsp;i++ &nbsp;或 &nbsp;++i &nbsp;作用是一样的，不少书上都说推荐写成 &nbsp;++i &nbsp;的形式，却从来没说明道理。 &nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 为什么要推荐写成 &nbsp;++i &nbsp;呢？&nbsp;&nbsp;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="COLOR: red">i++; &nbsp;// &nbsp;有一个临时变量 &nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ++i; &nbsp;// &nbsp;无临时变量</span>&nbsp;&nbsp;<br><br>有篇文章讨论过<br>for &nbsp;( &nbsp;int &nbsp;i &nbsp;= &nbsp;0; &nbsp;i &nbsp;&lt; &nbsp;100; &nbsp;i++ &nbsp;) &nbsp; &nbsp;<br>{ &nbsp; &nbsp;<br>&nbsp; &nbsp; &nbsp; &nbsp;/* &nbsp;&#8230;&#8230;&#8230;&#8230; &nbsp;*/ &nbsp; &nbsp;<br>}&nbsp;&nbsp;<br>但是很少有人想过代码背后隐藏的问题。读过STL源代码的人，都会对下面的代码一定很熟悉。&nbsp;&nbsp;&nbsp;&nbsp;<br>template&lt;class &nbsp;_II, &nbsp;class &nbsp;_OI&gt; &nbsp;inline &nbsp; &nbsp;<br>_OI &nbsp;copy( &nbsp;_II &nbsp;_F, &nbsp;_II &nbsp;_L, &nbsp;_OI &nbsp;_X &nbsp;) &nbsp; &nbsp;<br>{ &nbsp; &nbsp;<br>&nbsp; &nbsp; &nbsp; &nbsp;for &nbsp;( &nbsp;; &nbsp;_F &nbsp;!= &nbsp;_L; &nbsp;++_X, &nbsp;++_F &nbsp;) &nbsp; &nbsp;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;*_X &nbsp;= &nbsp;*_F; &nbsp; &nbsp;<br>&nbsp; &nbsp; &nbsp; &nbsp;return &nbsp;(_X); &nbsp; &nbsp;<br>} &nbsp; &nbsp;<br>// &nbsp;摘自Visual &nbsp;C++ &nbsp;6.0 &nbsp;STL实现，文件：xutility。&nbsp;&nbsp;&nbsp;&nbsp;<br>为什么它不写成&nbsp;&nbsp;&nbsp;&nbsp;<br><br>template&lt;class &nbsp;_II, &nbsp;class &nbsp;_OI&gt; &nbsp;inline &nbsp; &nbsp;<br>_OI &nbsp;copy( &nbsp;_II &nbsp;_F, &nbsp;_II &nbsp;_L, &nbsp;_OI &nbsp;_X &nbsp;) &nbsp; &nbsp;<br>{for &nbsp;( &nbsp;; &nbsp;_F &nbsp;!= &nbsp;_L; &nbsp;_X++, &nbsp;_F++ &nbsp;) &nbsp; &nbsp;<br>&nbsp; &nbsp; &nbsp; &nbsp;*_X &nbsp;= &nbsp;*_F; &nbsp; &nbsp;<br>&nbsp; &nbsp; &nbsp; &nbsp;return &nbsp;(_X); &nbsp; &nbsp;<br>}&nbsp;&nbsp;<br><br>看完这篇文章，你就可以知道这样写的理由。 &nbsp; &nbsp;<br>&nbsp;<br>C++是一种非常强大的语言，它赋予了它的使用者和他的创建者相同的权力。每一个内在的数据类型所支持的操作，你几乎都可以为自己定义的类型实现。运算符重载是其中的重要组成部分。 &nbsp; &nbsp;<br>&nbsp;<br>对于一个类CInt的运算符（这里只讨论加法），我们一般会这样实现：&nbsp;&nbsp;&nbsp;&nbsp;<br>class &nbsp;CInt &nbsp; &nbsp;<br>{ &nbsp; &nbsp;<br>public: &nbsp; &nbsp;<br>&nbsp; &nbsp; &nbsp; &nbsp;CInt&amp; &nbsp;operator &nbsp;++(); &nbsp; &nbsp;<br>&nbsp; &nbsp; &nbsp; &nbsp;CInt &nbsp;operator &nbsp;++( &nbsp;int &nbsp;); &nbsp; &nbsp;<br>&nbsp; &nbsp; &nbsp; &nbsp;CInt&amp; &nbsp;operator &nbsp;+=( &nbsp;const &nbsp;CInt&amp; &nbsp;that &nbsp;); &nbsp; &nbsp;<br>}; &nbsp; &nbsp;<br>&nbsp;<br>CInt &nbsp;operator &nbsp;+( &nbsp;const &nbsp;CInt&amp; &nbsp;this, &nbsp;const &nbsp;CInt&amp; &nbsp;that &nbsp;); &nbsp;<br>&nbsp;<br>&nbsp;<br>其中，CInt&amp; &nbsp;operator &nbsp;++();对应于++i;(如果i是CInt的一个实例，下同)返回引用的原因是因为在C++里，++i的结果应该是一个左值。对这个函数的调用，除了运算本身以外，并没有什么开销。（除了隐含的this以外，无传递参数，只有一个引用返回值，所以没有新的实例被创建） &nbsp; &nbsp;<br>CInt &nbsp;operator &nbsp;++( &nbsp;int &nbsp;); &nbsp;对应于i++;那个int是无意义的，只是为了把前缀运算和后缀运算区分开。返回变量（而不是引用）的原因是因为在C++里，i++的结果应该是一个右值，并且是i在没有加之前的值（所以不能返回它的const引用）。在这个函数中，会创建一个临时变量，并把它作为返回值拷贝给调用者。 &nbsp; &nbsp;<br>CInt&amp; &nbsp;operator &nbsp;+=( &nbsp;const &nbsp;CInt&amp; &nbsp;that &nbsp;);对应于i &nbsp;= &nbsp;i &nbsp;+ &nbsp;j;传递一个参数，从理论上来说，它的开销和++I的开销是一样的，但是，如果你只是要对类的实例加一的话，应该用++I，因为那个函数可能为加一而特别优化过。（具体可以参见实例） &nbsp; &nbsp;<br>CInt &nbsp;operator &nbsp;+( &nbsp;const &nbsp;CInt&amp; &nbsp;this, &nbsp;const &nbsp;CInt&amp; &nbsp;that &nbsp;);对应于k &nbsp;= &nbsp;i &nbsp;+ &nbsp;j;这个函数的开销与i++相同，但是要注意的是，i++可能为加一而优化的。 &nbsp; &nbsp;<br>&nbsp;<br>为了能够显著的测出各个函数的具体效率，我使用了一个非常"大"的类，CVector，一个65536维的整型向量。测试结果为： &nbsp; &nbsp;<br>&nbsp;<br>Another &nbsp;+= &nbsp;One &nbsp;: &nbsp;4326 &nbsp; &nbsp;<br>Another++ &nbsp;: &nbsp;9274 &nbsp; &nbsp;<br>Another &nbsp;= &nbsp;Another &nbsp;+ &nbsp;One &nbsp;: &nbsp;9223 &nbsp; &nbsp;<br>++Another &nbsp;: &nbsp;2153 &nbsp; &nbsp;<br>&nbsp;<br>可以看出，同样是加一，++i可以比i++快很多。 &nbsp; &nbsp;<br>&nbsp;<br>当然，编译器的优化也很重要，在某些情况下，编译器可以将i++的速度优化到和++i一样。但是，为什么不直接写出++i呢？这样可以保证在任何情况下都能获得较快的执行速度，而不是去依赖于编译器的优化。（至少，Visual &nbsp;C++ &nbsp;6.0是不支持的）</p>
<img src ="http://www.cppblog.com/jlthero/aggbug/75553.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jlthero/" target="_blank">精灵童</a> 2009-03-04 22:12 <a href="http://www.cppblog.com/jlthero/articles/75553.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>