<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-3829096759039124721</id><updated>2012-02-16T01:27:42.680-08:00</updated><category term='sandbox'/><category term='boost'/><category term='未完成'/><category term='finance'/><category term='cplusplus'/><title type='text'>Bug's Rhapsody</title><subtitle type='html'>未来是一枚失落的指针，往昔是一片无法删除的内存</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://codeblog.zhengzhong.net/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3829096759039124721/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://codeblog.zhengzhong.net/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Zhong ZHENG</name><uri>https://profiles.google.com/106629979370891920105</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-uEokg-47neM/AAAAAAAAAAI/AAAAAAAADs8/WCNYNlWPrFk/s512-c/photo.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>10</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-3829096759039124721.post-6773706045416799135</id><published>2008-06-18T04:49:00.000-07:00</published><updated>2009-03-08T12:05:16.711-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='cplusplus'/><title type='text'>一个相当牛逼的C程序</title><content type='html'>&lt;pre class="prettyprint lang-c"&gt;/* mystery.c */&lt;br /&gt;#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;main(t,_,a)&lt;br /&gt;char *a;&lt;br /&gt;{return!0&amp;lt;t?t&amp;lt;3?main(-79,-13,a+main(-87,1-_,&lt;br /&gt;main(-86, 0, a+1 )+a)):1,t&amp;lt;_?main(t+1, _, a ):3,main ( -94, -27+t, a&lt;br /&gt;)&amp;amp;&amp;amp;t == 2 ?_&amp;lt;13 ?main ( 2, _+1, "%s %d %d\n" ):9:16:t&amp;lt;0?t&amp;lt;-72?main(_,&lt;br /&gt;t,"@n'+,#'/*{}w+/w#cdnr/+,{}r/*de}+,/*{*+,/w{%+,/w#q#n+,/#{l,+,/n{n+\&lt;br /&gt;,/+#n+,/#;#q#n+,/+k#;*+,/'r :'d*'3,}{w+K w'K:'+}e#';dq#'l q#'+d'K#!/\&lt;br /&gt;+k#;q#'r}eKK#}w'r}eKK{nl]'/#;#q#n'){)#}w'){){nl]'/+#n';d}rw' i;# ){n\&lt;br /&gt;l]!/n{n#'; r{#w'r nc{nl]'/#{l,+'K {rw' iK{;[{nl]'/w#q#\&lt;br /&gt;n'wk nw' iwk{KK{nl]!/w{%'l##w#' i; :{nl]'/*{q#'ld;r'}{nlwb!/*de}'c\&lt;br /&gt;;;{nl'-{}rw]'/+,}##'*}#nc,',#nw]'/+kd'+e}+;\&lt;br /&gt;#'rdq#w! nr'/ ') }+}{rl#'{n' ')# }'+}##(!!/")&lt;br /&gt;:t&amp;lt;-50?_==*a ?putchar(a[31]):main(-65,_,a+1):main((*a == '/')+t,_,a\&lt;br /&gt;+1 ):0&amp;lt;t?main ( 2, 2 , "%s"):*a=='/'||main(0,main(-61,*a, "!ek;dc \&lt;br /&gt;i@bK'(q)-[w]*%n+r3#l,{}:\nuwloca-O;m .vpbks,fxntdCeghiry"),a+1);}&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3829096759039124721-6773706045416799135?l=codeblog.zhengzhong.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeblog.zhengzhong.net/feeds/6773706045416799135/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://codeblog.zhengzhong.net/2008/06/blog-post.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3829096759039124721/posts/default/6773706045416799135'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3829096759039124721/posts/default/6773706045416799135'/><link rel='alternate' type='text/html' href='http://codeblog.zhengzhong.net/2008/06/blog-post.html' title='一个相当牛逼的C程序'/><author><name>Zhong ZHENG</name><uri>https://profiles.google.com/106629979370891920105</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-uEokg-47neM/AAAAAAAAAAI/AAAAAAAADs8/WCNYNlWPrFk/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3829096759039124721.post-1236571395111925842</id><published>2008-02-29T09:26:00.000-08:00</published><updated>2008-02-29T09:30:26.481-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='finance'/><title type='text'>Financial Date Algorithms</title><content type='html'>&lt;big&gt;&lt;b&gt;Day Count Conventions&lt;/b&gt;&lt;/big&gt;&lt;br /&gt;&lt;br /&gt;TODO:&lt;br /&gt;&lt;br /&gt;&lt;big&gt;&lt;b&gt;Rolling Conventions&lt;/b&gt;&lt;/big&gt;&lt;br /&gt;&lt;br /&gt;Firstly, given a start date and a maturity, the rolling conventions are used to determine the end date of the calculation period. Suppose today is 2007-02-28 (the last day of February), and we would like to generate a calculation period using a maturity of 6 months. The end date may be ambiguous as both 2007-08-28 and 2007-08-31 seem reasonable. In this case, the &lt;b&gt;non-end-of-month&lt;/b&gt; convention will generate 2007-08-28, while the &lt;b&gt;end-of-month&lt;/b&gt; convention will generate 2007-08-31.&lt;br /&gt;&lt;br /&gt;Secondly, if the start date or end date of a calculation period falls on a non-business day, the rolling conventions are also used to adjust the dates. There are 5 adjustment conventions:&lt;br /&gt;&lt;br /&gt;- &lt;b&gt;No Adjustment&lt;/b&gt;: the date will not be adjusted, even if it falls on a non-business day.&lt;br /&gt;- &lt;b&gt;Following&lt;/b&gt;: the non-business date will be adjusted to the first following day that is a business day.&lt;br /&gt;- &lt;b&gt;Preceding&lt;/b&gt;: the non-business date will be adjusted to the first preceding day that is a business day.&lt;br /&gt;- &lt;b&gt;Modified Following&lt;/b&gt;: the non-business date will be adjusted to the first following day that is a business day unless that day falls in the next calendar month, in which case that date will be the first preceding day that is a business day.&lt;br /&gt;- &lt;b&gt;Modified Preceding&lt;/b&gt;: the non-business date will be adjusted to the first preceding day that is a business day unless that day falls in the previous calendar month, in which case that date will be the first following day that is a business day.&lt;br /&gt;&lt;br /&gt;Besides, there are 2 special conventions for adjusting dates:&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Two business days prior to third Wednesday of the month&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;This convention is related to exchange traded contracts where trading stops two business days prior to the third Wednesday of the month. For annual, semi-annual, quarterly or monthly frequencies, generated dates are adjusted to fall 2 business days prior to the third Wednesday of the month. For all other frequencies, dates are generated as usual with no adjustment. The maturity date is not adjusted.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Third Wednesday&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;This convention is related to exchange traded contracts where trading stops on the third Wednesday of the month. For annual, semi-annual, quarterly or monthly frequencies, generated dates are adjusted to fall on the third Wednesday of the month. For all other frequencies, dates are generated as usual with no adjustment. The maturity date is not adjusted.&lt;br /&gt;&lt;br /&gt;&lt;big&gt;&lt;b&gt;Irregular Calculation Period Conventions&lt;/b&gt;&lt;/big&gt;&lt;br /&gt;&lt;br /&gt;For financial products such as interest rate swaps, we need to generate a sequence of calculation periods. Given a start date, an end date and a frequency, there may be a remaining irregular calculation period. For example, if today (start date) is 2008-02-01, the maturity date of the swap (end date) is 2009-03-01, and the frequency is 3 months. In this case, we may use the following conventions (stubs) to determine how to generate the irregular calculation periods:&lt;br /&gt;&lt;br /&gt;- &lt;b&gt;Short Initial&lt;/b&gt;: generate an irregular calculation period at the beginning of the sequence, which is shorter than the frequency.&lt;br /&gt;- &lt;b&gt;Short Final&lt;/b&gt;: generate an irregular calculation period the end of the sequence, which is shorter than the frequency.&lt;br /&gt;- &lt;b&gt;Long Initial&lt;/b&gt;: generate an irregular calculation period at the beginning of the sequence, which is longer than the frequency.&lt;br /&gt;- &lt;b&gt;Long Final&lt;/b&gt;: generate an irregular calculation period at the end of the sequence, which is longer than the frequency.&lt;br /&gt;&lt;br /&gt;&lt;big&gt;&lt;b&gt;References&lt;/b&gt;&lt;/big&gt;&lt;br /&gt;&lt;br /&gt;- &lt;a class="link_ext" href="http://www.euribor.org/"&gt;EURIBOR and EONIA&lt;/a&gt;&lt;br /&gt;- &lt;a class="link_ext" href="http://www.bba.org.uk/"&gt;BBA&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3829096759039124721-1236571395111925842?l=codeblog.zhengzhong.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeblog.zhengzhong.net/feeds/1236571395111925842/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://codeblog.zhengzhong.net/2008/02/financial-date-algorithms.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3829096759039124721/posts/default/1236571395111925842'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3829096759039124721/posts/default/1236571395111925842'/><link rel='alternate' type='text/html' href='http://codeblog.zhengzhong.net/2008/02/financial-date-algorithms.html' title='Financial Date Algorithms'/><author><name>Zhong ZHENG</name><uri>https://profiles.google.com/106629979370891920105</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-uEokg-47neM/AAAAAAAAAAI/AAAAAAAADs8/WCNYNlWPrFk/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3829096759039124721.post-7017360234080808601</id><published>2008-02-11T09:17:00.001-08:00</published><updated>2008-02-11T09:17:54.020-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='finance'/><title type='text'>The Greek Letters</title><content type='html'>&lt;big&gt;&lt;b&gt;The Greek Letters&lt;/b&gt;&lt;/big&gt;&lt;br /&gt;&lt;br /&gt;Each Greek letter measures a different dimension to the risk in a portfolio and the aim of a trader is to manage the Greeks so that all risks are acceptable.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Delta&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;The &lt;i&gt;delta&lt;/i&gt; of a portfolio is defined as the rate of change of the portfolio price with respect to the price of the underlying asset.&lt;br /&gt;&lt;br /&gt;The delta of a portfolio can be calculated from the deltas of the individual derivatives in the portfolio.&lt;br /&gt;&lt;br /&gt;TODO: delta hedging.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Theta&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;The &lt;i&gt;theta&lt;/i&gt; of a portfolio is the rate of change of the value of the portfolio with respect to the passage of time with all else remaining the same. Theta is sometimes referred to as the time decay of the portfolio.&lt;br /&gt;&lt;br /&gt;Note that theta is not the same type of hedge parameter as delta. There is uncertainty about the future price of the underlying asset, but there is no certainty about the passage of time. It makes sense to hedge against changes in the price of the underlying asset, but it does not make any sense to hedge against the effect of the passage of time on a portfolio. In spite of this, many traders regard theta as a useful descriptive statistic for a portfolio. This is because in a delta-neutral portfolio, theta is a proxy of gamma.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Gamma&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;The &lt;i&gt;gamma&lt;/i&gt; of a portfolio is the rate of change of the portfolio's delta with respect to the price of the underlying asset. It is the second partial derivative of the portfolio with respect to asset price.&lt;br /&gt;&lt;br /&gt;If gamma is small, delta changes slowly, and adjustments to keep a portfolio delta-neutral need to be made only relatively infrequently. However, if gamma is large in absolute terms, delta is highly sensitive to the price of the underlying asset. It is then quite risky to leave a delta-neutral portfolio unchanged for any length of time.&lt;br /&gt;&lt;br /&gt;TODO: gamma hedging.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Relationship Between Delta, Theta and Gamma&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;TODO: Who can tell me how to write mathematical formula in HTML?&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Vega&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;The &lt;i&gt;vega&lt;/i&gt; of a portfolio is the rate of change of the value of the portfolio with respect to the volatility of the underlying asset.&lt;br /&gt;&lt;br /&gt;If vega is high in absolute terms, the portfolio's value is very sensitive to small changes in volatility. If vega is low in absolute terms, volatility changes have relatively little impact on the value of the portfolio.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Rho&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;The &lt;i&gt;rho&lt;/i&gt; of a portfolio is the rate of change of the value of the portfolio with respect to the interest rate.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3829096759039124721-7017360234080808601?l=codeblog.zhengzhong.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeblog.zhengzhong.net/feeds/7017360234080808601/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://codeblog.zhengzhong.net/2008/02/greek-letters.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3829096759039124721/posts/default/7017360234080808601'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3829096759039124721/posts/default/7017360234080808601'/><link rel='alternate' type='text/html' href='http://codeblog.zhengzhong.net/2008/02/greek-letters.html' title='The Greek Letters'/><author><name>Zhong ZHENG</name><uri>https://profiles.google.com/106629979370891920105</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-uEokg-47neM/AAAAAAAAAAI/AAAAAAAADs8/WCNYNlWPrFk/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3829096759039124721.post-1546805315176736070</id><published>2008-01-16T05:31:00.000-08:00</published><updated>2008-01-18T15:00:43.593-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='finance'/><title type='text'>Vanilla Interest Rate Derivatives (2)</title><content type='html'>&lt;big&gt;&lt;b&gt;Range Accrual Note (RAN)&lt;/b&gt;&lt;/big&gt;&lt;br /&gt;&lt;br /&gt;A range accrual note (RAN) is similar to a fixed rate bond, except that interest only accrues on days when a reference rate falls within a specified range. So its payoff depends on the volatility of the reference rate: the lower the reference rate's volatility is, the higher the RAN's payoff is.&lt;br /&gt;&lt;br /&gt;Suppose that in a RAN, the fixed rate is &lt;i&gt;fix&lt;/i&gt;, and the reference rate is &lt;i&gt;R_{ref}&lt;/i&gt;. The reference rate &lt;i&gt;R_{ref}&lt;/i&gt; is observed every day during a cash flow period, and is tested against the specified range &lt;i&gt;[L, U]&lt;/i&gt;. Define &lt;i&gt;n&lt;/i&gt; as the number of days in the period when &lt;i&gt;(L &amp;lt; R_{ref} &amp;lt; U)&lt;/i&gt;, and &lt;i&gt;N&lt;/i&gt; as the total number of days in the period. The payoff rate of the RAN is given by the following formula:&lt;br /&gt;&lt;br /&gt;&lt;pre class="formula"&gt;R_{payoff} = fix * (n / N)&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;If we replace the fixed rate &lt;i&gt;fix&lt;/i&gt; by a leveraged floating rate &lt;i&gt;(L * R + fix)&lt;/i&gt;, where &lt;i&gt;R&lt;/i&gt; is a floating rate, and the leverage &lt;i&gt;L&lt;/i&gt; and the fixed rate &lt;i&gt;fix&lt;/i&gt; are both constant, we can obtain a floating rate range accrual note. Its payoff rate is given by the following formula:&lt;br /&gt;&lt;br /&gt;&lt;pre class="formula"&gt;R_{payoff} = (L * R + fix) * (n / N)&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;big&gt;&lt;b&gt;Range Accrual Spread Note (SRAN)&lt;/b&gt;&lt;/big&gt;&lt;br /&gt;&lt;br /&gt;In a range accrual note, if we replace the reference rate &lt;i&gt;R_{ref}&lt;/i&gt; by a spread of two reference rates &lt;i&gt;(R1 - R2)&lt;/i&gt;, we can obtain a range accrual spread note (SRAN). In a SRAN, the condition to check is &lt;i&gt;(L &amp;lt; R1 - R2 &amp;lt; U)&lt;/i&gt;.&lt;br /&gt;&lt;br /&gt;&lt;big&gt;&lt;b&gt;Dual Range Accrual Spread Note&lt;/b&gt;&lt;/big&gt;&lt;br /&gt;&lt;br /&gt;A dual range accrual spread note is a range accrual note where the condition to check is based on two reference spreads &lt;i&gt;(R11 - R12)&lt;/i&gt; and &lt;i&gt;(R21 - R22)&lt;/i&gt;, and two ranges &lt;i&gt;[L1, U1]&lt;/i&gt; and &lt;i&gt;[L2, U2]&lt;/i&gt;: &lt;i&gt;((L1 &amp;lt; R11 - R12 &amp;lt; U1) and (L2 &amp;lt; R21 - R22 &amp;lt; U2))&lt;/i&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3829096759039124721-1546805315176736070?l=codeblog.zhengzhong.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeblog.zhengzhong.net/feeds/1546805315176736070/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://codeblog.zhengzhong.net/2008/01/vanilla-interest-rate-derivatives-2.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3829096759039124721/posts/default/1546805315176736070'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3829096759039124721/posts/default/1546805315176736070'/><link rel='alternate' type='text/html' href='http://codeblog.zhengzhong.net/2008/01/vanilla-interest-rate-derivatives-2.html' title='Vanilla Interest Rate Derivatives (2)'/><author><name>Zhong ZHENG</name><uri>https://profiles.google.com/106629979370891920105</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-uEokg-47neM/AAAAAAAAAAI/AAAAAAAADs8/WCNYNlWPrFk/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3829096759039124721.post-1280306797062952635</id><published>2008-01-16T01:58:00.000-08:00</published><updated>2008-01-16T04:39:33.305-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='finance'/><title type='text'>Vanilla Interest Rate Derivatives (1)</title><content type='html'>&lt;big&gt;&lt;b&gt;Function Definitions&lt;/b&gt;&lt;/big&gt;&lt;br /&gt;&lt;br /&gt;TODO: define some functions such as min, max, bound, etc.&lt;br /&gt;&lt;br /&gt;&lt;big&gt;&lt;b&gt;Interest Rate Cap, Floor and Straddle&lt;/b&gt;&lt;/big&gt;&lt;br /&gt;&lt;br /&gt;An interest rate cap is a derivative in which the buyer receives money at the end of each cash flow period in which the specified floating rate &lt;i&gt;R&lt;/i&gt; exceeds the agreed strike price &lt;i&gt;K&lt;/i&gt;. An example of a cap would be an agreement to receive money for each month the LIBOR rate exceeds 2.5%.&lt;br /&gt;&lt;br /&gt;The interest rate cap can be analyzed as a series of European call options or caplets which exists for each cash flow period the cap agreement is in existence. In formulas, the caplet rate that will be applied on the notional for a cash flow period is:&lt;br /&gt;&lt;br /&gt;&lt;pre class="formula"&gt;R_{payoff} = max(R - K, 0)&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Where &lt;i&gt;R&lt;/i&gt; is the underlying floating rate, and &lt;i&gt;K&lt;/i&gt; is the cap strike.&lt;br /&gt;&lt;br /&gt;An interest rate floor is a series of European put options or floorlets on a specified floating rate &lt;i&gt;R&lt;/i&gt;. The buyer of the floor receives money if on the maturity of any of the floorlets, the fixed floating rate &lt;i&gt;R&lt;/i&gt; is below the agreed strike &lt;i&gt;K&lt;/i&gt; of the floor. In formulas, the floorlet rate that will be applied on the notional for a cash flow period is:&lt;br /&gt;&lt;br /&gt;&lt;pre class="formula"&gt;R_{payoff} = max(K - R, 0)&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;An interest rate straddle is a portfolio of an interest rate cap and an interest rate floor on the same floating rate &lt;i&gt;R&lt;/i&gt; with the same strike &lt;i&gt;K&lt;/i&gt;. The payoff rate of a straddle cash flow (a straddle-let) is:&lt;br /&gt;&lt;br /&gt;&lt;pre class="formula"&gt;R_{payoff} = max(R - K, 0) + max(K - R, 0) = abs(R - K)&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;An interest rate straddle can be replicated by a portfolio of an interest rate cap and an interest rate floor.&lt;br /&gt;&lt;br /&gt;&lt;big&gt;&lt;b&gt;Leveraged Cap/Floor&lt;/b&gt;&lt;/big&gt;&lt;br /&gt;&lt;br /&gt;A capped/floored floating rate is a floating rate &lt;i&gt;R&lt;/i&gt; with an upper bound &lt;i&gt;U&lt;/i&gt; and a lower bound &lt;i&gt;L&lt;/i&gt;. The payoff rate of the capped/floored floating rate is:&lt;br /&gt;&lt;br /&gt;&lt;pre class="formula"&gt;&lt;br /&gt;R_{payoff} = bound(R, L, U)&lt;br /&gt;           = U &lt;i&gt;(if R &amp;gt; U)&lt;/i&gt;, or&lt;br /&gt;             R &lt;i&gt;(if L &amp;lt;= R &amp;lt;= U)&lt;/i&gt;, or&lt;br /&gt;             L &lt;i&gt;(if R &amp;lt; L)&lt;/i&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;We can re-write the formula above as the following:&lt;br /&gt;&lt;br /&gt;&lt;pre class="formula"&gt;R_{payoff} = R + max(L - R, 0) - max(R - U, 0)&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;So, the capped/floored payoff rate may be replicated using a portfolio of:&lt;br /&gt;&lt;br /&gt;- &lt;i&gt;+1&lt;/i&gt; floating rate &lt;i&gt;R&lt;/i&gt;,&lt;br /&gt;- &lt;i&gt;+1&lt;/i&gt; floor on the floating rate &lt;i&gt;R&lt;/i&gt; with a strike of &lt;i&gt;L&lt;/i&gt;,&lt;br /&gt;- &lt;i&gt;-1&lt;/i&gt; cap on the floating rate &lt;i&gt;R&lt;/i&gt; with a strike of &lt;i&gt;U&lt;/i&gt;.&lt;br /&gt;&lt;br /&gt;In a capped/floored floating rate, if we replace the underlying floating rate &lt;i&gt;R&lt;/i&gt; by a structured rate &lt;i&gt;(L * R + fix)&lt;/i&gt;, where the leverage &lt;i&gt;L&lt;/i&gt; and the fixed rate &lt;i&gt;fix&lt;/i&gt; are constants, we can obtain a leveraged cap/floor. The payoff rate is:&lt;br /&gt;&lt;br /&gt;&lt;pre class="formula"&gt;R_{payoff} = bound(L * R + fix, L, U)&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The payoff rate may be replicated using a portfolio of:&lt;br /&gt;&lt;br /&gt;- &lt;i&gt;+1&lt;/i&gt; leveraged floating rate &lt;i&gt;R'&lt;/i&gt;, where &lt;i&gt;R' = L * R + fix&lt;/i&gt;,&lt;br /&gt;- &lt;i&gt;+1&lt;/i&gt; floor on the leveraged floating rate &lt;i&gt;R'&lt;/i&gt; with a strike of &lt;i&gt;L&lt;/i&gt;,&lt;br /&gt;- &lt;i&gt;-1&lt;/i&gt; cap on the leveraged floating rate &lt;i&gt;R'&lt;/i&gt; with a strike of &lt;i&gt;U&lt;/i&gt;.&lt;br /&gt;&lt;br /&gt;&lt;big&gt;&lt;b&gt;Leveraged Spread Cap/Floor&lt;/b&gt;&lt;/big&gt;&lt;br /&gt;&lt;br /&gt;In a capped/floored floating rate, if we replace the underlying floating rate &lt;i&gt;R&lt;/i&gt; by a leveraged spread &lt;i&gt;(L * (L1 * R1 - L2 * R2) + fix)&lt;/i&gt;, where &lt;i&gt;R1&lt;/i&gt; and &lt;i&gt;R2&lt;/i&gt; are two floating rates (such as 3-month LIBOR and 6-month LIBOR), and the leverages &lt;i&gt;L&lt;/i&gt;, &lt;i&gt;L1&lt;/i&gt;, &lt;i&gt;L2&lt;/i&gt;, and the fixed rate &lt;i&gt;fix&lt;/i&gt; are constants, we can obtain a leveraged spread cap/floor. The payoff rate is:&lt;br /&gt;&lt;br /&gt;&lt;pre class="formula"&gt;R_{payoff} = bound(L * (L1 * R1 - L2 * R2) + fix, L, U)&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;big&gt;&lt;b&gt;Digit Cap/Floor&lt;/b&gt;&lt;/big&gt;&lt;br /&gt;&lt;br /&gt;The payoff rates of a digit cap and a digit floor are defined by the following formulas:&lt;br /&gt;&lt;br /&gt;&lt;pre class="formula"&gt;&lt;br /&gt;For digit cap:&lt;br /&gt;    R_{payoff} = fix &lt;i&gt;(if R &amp;gt; K)&lt;/i&gt;, or&lt;br /&gt;                 0   &lt;i&gt;(otherwise)&lt;/i&gt;&lt;br /&gt;For digit floor:&lt;br /&gt;    R_{payoff} = fix &lt;i&gt;(if R &amp;lt; K)&lt;/i&gt;, or&lt;br /&gt;                 0   &lt;i&gt;(otherwise)&lt;/i&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;By using a proper epsilon &lt;i&gt;e&lt;/i&gt; which is small enough, we can approximately replicate a digit cap using:&lt;br /&gt;&lt;br /&gt;- &lt;i&gt;+(fix/2e)&lt;/i&gt; cap on the floating rate &lt;i&gt;R&lt;/i&gt; with a strike of &lt;i&gt;(K - e)&lt;/i&gt;,&lt;br /&gt;- &lt;i&gt;-(fix/2e)&lt;/i&gt; cap on the floating rate &lt;i&gt;R&lt;/i&gt; with a strike of &lt;i&gt;(K + e)&lt;/i&gt;.&lt;br /&gt;&lt;br /&gt;We can approximately replicate a digit floor the same way, using:&lt;br /&gt;&lt;br /&gt;- &lt;i&gt;+(fix/2e)&lt;/i&gt; floor on the floating rate &lt;i&gt;R&lt;/i&gt; with a strike of &lt;i&gt;(K + e)&lt;/i&gt;,&lt;br /&gt;- &lt;i&gt;-(fix/2e)&lt;/i&gt; floor on the floating rate &lt;i&gt;R&lt;/i&gt; with a strike of &lt;i&gt;(K - e)&lt;/i&gt;.&lt;br /&gt;&lt;br /&gt;&lt;big&gt;&lt;b&gt;Barrier Cap/Floor&lt;/b&gt;&lt;/big&gt;&lt;br /&gt;&lt;br /&gt;There are four types of barrier cap/floor: cap-up-and-in, cap-up-and-out, floor-down-and-in, and floor-down-and-out. Their payoff rates are&lt;br /&gt;defined by the following furmulas:&lt;br /&gt;&lt;br /&gt;&lt;pre class="formula"&gt;&lt;br /&gt;For cap-up-and-in:&lt;br /&gt;    R_{payoff} = max(R - K, 0) &lt;i&gt;(if R &amp;lt; B)&lt;/i&gt;, or&lt;br /&gt;                 0             &lt;i&gt;(otherwise)&lt;/i&gt;&lt;br /&gt;For cap-up-and-out:&lt;br /&gt;    R_{payoff} = max(R - K, 0) &lt;i&gt;(if R &amp;gt; B)&lt;/i&gt;, or&lt;br /&gt;                 0             &lt;i&gt;(otherwise)&lt;/i&gt;&lt;br /&gt;For floor-down-and-in:&lt;br /&gt;    R_{payoff} = max(K - R, 0) &lt;i&gt;(if R &amp;lt; B)&lt;/i&gt;, or&lt;br /&gt;                 0             &lt;i&gt;(otherwise)&lt;/i&gt;&lt;br /&gt;For floor-down-and-out:&lt;br /&gt;    R_{payoff} = max(K - R, 0) &lt;i&gt;(if R &amp;gt; B)&lt;/i&gt;, or&lt;br /&gt;                 0             &lt;i&gt;(otherwise)&lt;/i&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Where &lt;i&gt;R&lt;/i&gt; is the floating rate, &lt;i&gt;K&lt;/i&gt; is the strike, and &lt;i&gt;B&lt;/i&gt; is the barrier. In a barrier cap, the barrier should be greater than the strike &lt;i&gt;(B &amp;gt; K)&lt;/i&gt;. In a barrier floor, the barrier should be less than the strike &lt;i&gt;(B &amp;lt; K)&lt;/i&gt;.&lt;br /&gt;&lt;br /&gt;We can use the following portfolio to replicate a cap-up-and-in:&lt;br /&gt;&lt;br /&gt;- &lt;i&gt;+1&lt;/i&gt; cap on the floating rate &lt;i&gt;R&lt;/i&gt; with a strike of &lt;i&gt;K&lt;/i&gt;,&lt;br /&gt;- &lt;i&gt;-1&lt;/i&gt; digit cap on the floating rate &lt;i&gt;R&lt;/i&gt; with a strike of &lt;i&gt;B&lt;/i&gt; and a fixed rate of &lt;i&gt;(B - K)&lt;/i&gt;,&lt;br /&gt;- &lt;i&gt;-1&lt;/i&gt; cap on the floating rate &lt;i&gt;R&lt;/i&gt; with a strike of &lt;i&gt;B&lt;/i&gt;.&lt;br /&gt;&lt;br /&gt;Since a portfolio of a cap-up-and-in and a cap-up-and-out on the same floating rate &lt;i&gt;R&lt;/i&gt; with the same strike &lt;i&gt;K&lt;/i&gt; and the same barrier &lt;i&gt;B&lt;/i&gt; gives the payoff of a cap on the floating rate &lt;i&gt;R&lt;/i&gt; with the strike &lt;i&gt;K&lt;/i&gt;, we can replicate a cap-up-and-out using the following portfolio:&lt;br /&gt;&lt;br /&gt;- &lt;i&gt;+1&lt;/i&gt; cap on the floating rate &lt;i&gt;R&lt;/i&gt; with a strike of &lt;i&gt;K&lt;/i&gt;,&lt;br /&gt;- &lt;i&gt;-1&lt;/i&gt; cap-up-and-in on the floating rate &lt;i&gt;R&lt;/i&gt; with a strike of &lt;i&gt;K&lt;/i&gt; and a barrier of &lt;i&gt;B&lt;/i&gt;.&lt;br /&gt;&lt;br /&gt;We can use the following portfolio to replicate a floor-down-and-out:&lt;br /&gt;&lt;br /&gt;- &lt;i&gt;+1&lt;/i&gt; floor on the floating rate &lt;i&gt;R&lt;/i&gt; with a strike of &lt;i&gt;K&lt;/i&gt;,&lt;br /&gt;- &lt;i&gt;-1&lt;/i&gt; digit floor on the floating rate &lt;i&gt;R&lt;/i&gt; with a strike of &lt;i&gt;B&lt;/i&gt; and a fixed rate of &lt;i&gt;(K - B)&lt;/i&gt;,&lt;br /&gt;- &lt;i&gt;-1&lt;/i&gt; floor on the floating rate &lt;i&gt;R&lt;/i&gt; with a strike of &lt;i&gt;B&lt;/i&gt;.&lt;br /&gt;&lt;br /&gt;And the following portfolio to replicate a floor-down-and-in:&lt;br /&gt;&lt;br /&gt;- &lt;i&gt;+1&lt;/i&gt; floor on the floating rate &lt;i&gt;R&lt;/i&gt; with a strike of &lt;i&gt;K&lt;/i&gt;,&lt;br /&gt;- &lt;i&gt;-1&lt;/i&gt; floor-down-and-out on the floating rate &lt;i&gt;R&lt;/i&gt; with a strike of &lt;i&gt;K&lt;/i&gt; and a barrier of &lt;i&gt;B&lt;/i&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3829096759039124721-1280306797062952635?l=codeblog.zhengzhong.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeblog.zhengzhong.net/feeds/1280306797062952635/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://codeblog.zhengzhong.net/2008/01/vanilla-interest-rate-derivatives.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3829096759039124721/posts/default/1280306797062952635'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3829096759039124721/posts/default/1280306797062952635'/><link rel='alternate' type='text/html' href='http://codeblog.zhengzhong.net/2008/01/vanilla-interest-rate-derivatives.html' title='Vanilla Interest Rate Derivatives (1)'/><author><name>Zhong ZHENG</name><uri>https://profiles.google.com/106629979370891920105</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-uEokg-47neM/AAAAAAAAAAI/AAAAAAAADs8/WCNYNlWPrFk/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3829096759039124721.post-6303019342757800907</id><published>2008-01-08T08:41:00.000-08:00</published><updated>2009-03-08T12:03:56.020-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='未完成'/><category scheme='http://www.blogger.com/atom/ns#' term='cplusplus'/><category scheme='http://www.blogger.com/atom/ns#' term='boost'/><title type='text'>Boost Tokenizer笔记</title><content type='html'>&lt;big&gt;&lt;b&gt;Boost Tokenizer模板类&lt;/b&gt;&lt;/big&gt;&lt;br /&gt;&lt;br /&gt;先看boost::tokenizer模板类的声明：&lt;br /&gt;&lt;br /&gt;&lt;pre class="prettyprint lang-cpp"&gt;// boost::tokenizer template class.&lt;br /&gt;template&amp;lt;&lt;br /&gt;  class TokenizerFunc = char_delimiters_separator&amp;lt;char&amp;gt;,&lt;br /&gt;  class Iterator = std::string::const_iterator,&lt;br /&gt;  class Type = std::string&lt;br /&gt;&amp;gt; class tokenizer;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;boost::tokenizer模板类的第一个模板参数TokenizerFunc是一个方法对象，用于对序列进行语法分析，以寻找token。第二个模板参数Iterator定义了被分析的序列的iterator类型。第三个模板参数Type定义了序列容器的类型。默认情况下，boost::tokenizer用于分析字符串序列，所以Iterator的默认类型是std::string::const_iterator，而Type的默认类型是std::string。&lt;br /&gt;&lt;br /&gt;&lt;big&gt;&lt;b&gt;TokenizerFunc&lt;/b&gt;&lt;/big&gt;&lt;br /&gt;&lt;br /&gt;根据Boost Tokenizer的文档：TokenizerFunc是一个方法对象（functor），它的作用是对一个给定的序列进行语法分析，直到找到了一个token为止，或者直到序列结束为止。&lt;br /&gt;&lt;br /&gt;A TokenizerFunction is a functor whose purpose is to parse a given sequence until exactly 1 token has been found or the end is reached. It then updates the token, and informs the caller of the location in the sequence of the next element immediately after the last element of the sequence that was parsed for the current token.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;TODO:&lt;/b&gt; How to implement a customized tokenizer func?&lt;br /&gt;&lt;br /&gt;Boost Tokenizer库中提供了三个实现好的TokenizerFunc：&lt;br /&gt;&lt;br /&gt;- escaped_list_separator&lt;br /&gt;- offset_separator&lt;br /&gt;- char_delimiters_separator&lt;br /&gt;&lt;br /&gt;&lt;big&gt;&lt;b&gt;Char Delimiters Separator&lt;/b&gt;&lt;/big&gt;&lt;br /&gt;&lt;br /&gt;boost::char_delimiters_separator使用单个字符作为token的分隔符。分隔符分为两类：返回型分隔符和非返回型分隔符。以下解释这两类分隔符的区别。&lt;br /&gt;&lt;br /&gt;假设我们需要tokenize一个用于表示方程组的字符串，如下：&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;x + y = 100; x-y=10;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;我们希望获得的token是：&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;token[0] = "x"&lt;br /&gt;token[1] = "+"&lt;br /&gt;token[2] = "y"&lt;br /&gt;token[3] = "="&lt;br /&gt;token[4] = "100"&lt;br /&gt;token[5] = "x"&lt;br /&gt;token[6] = "-"&lt;br /&gt;token[7] = "y"&lt;br /&gt;token[8] = "="&lt;br /&gt;token[9] = "10"&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;在这种情况下，字符';'和空格字符的作用仅仅是分隔token，它们本身并不是token，因此它们是非返回型分隔符，不会被tokenizer作为一个token返回；而字符'+'，'-'和'='的作用不仅是分隔token，它们本身也是token，因此它们属于返回型分隔符，会被tokenizer作为一个token返回。&lt;br /&gt;&lt;br /&gt;boost::char_delimiters_separator的构造函数声明如下：&lt;br /&gt;&lt;br /&gt;&lt;pre class="prettyprint lang-cpp"&gt;// boost::char_delimiters_separator template class.&lt;br /&gt;template&amp;lt;class Char, class Traits = std::char_traits&amp;lt;Char&amp;gt; &amp;gt;&lt;br /&gt;class char_delimiters_separator {&lt;br /&gt;public:&lt;br /&gt;  // ...&lt;br /&gt;  explicit char_delimiters_separator(&lt;br /&gt;      bool return_delims = false,&lt;br /&gt;      const Char* returnable = "",&lt;br /&gt;      const Char* nonreturnable = "");&lt;br /&gt;  //...&lt;br /&gt;};&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;第一个参数return_delims决定了是否某些分隔符可以作为token被返回，注意它的默认值是false。第二个参数returnable定义了一组返回型的分隔符，注意仅当第一个参数的值为true时，这些返回型的分隔符才会被作为token返回。第三个参数nonreturnable定义了一组非返回型的分隔符。&lt;br /&gt;&lt;br /&gt;以下代码使用了boost::tokenizer来分析上述表示方程组的字符串，并获得我们期望的结果：&lt;br /&gt;&lt;br /&gt;&lt;pre class="prettyprint lang-cpp"&gt;&lt;br /&gt;#include &amp;lt;boost/tokenizer.hpp&amp;gt;&lt;br /&gt;#include &amp;lt;string&amp;gt;&lt;br /&gt;#include &amp;lt;iostream&amp;gt;&lt;br /&gt;&lt;br /&gt;int main(int, char**) {&lt;br /&gt;  typedef boost::char_delimiters_separator&amp;lt;char&amp;gt; separator;&lt;br /&gt;  typedef boost::tokenizer&amp;lt;Separator&amp;gt;            tokenizer;&lt;br /&gt;  std::string str = "x + y = 100; x-y=10;";&lt;br /&gt;  separator sep(true, "+-=", " ;");&lt;br /&gt;  tokenizer tok(str, sep);&lt;br /&gt;  unsigned int count = 0;&lt;br /&gt;  for (tokenizer::iterator i = tok.begin();&lt;br /&gt;                           i != tok.end();&lt;br /&gt;                           ++i, ++count) {&lt;br /&gt;    std::cout &amp;lt;&amp;lt; "token[" &amp;lt;&amp;lt; count &amp;lt;&amp;lt; "] = "&lt;br /&gt;              &amp;lt;&amp;lt; (*i) &amp;lt;&amp;lt; std::endl;&lt;br /&gt;  }&lt;br /&gt;  return 0;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;TODO:&lt;/b&gt; How to use escaped_list_separator and offset_separator?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3829096759039124721-6303019342757800907?l=codeblog.zhengzhong.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeblog.zhengzhong.net/feeds/6303019342757800907/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://codeblog.zhengzhong.net/2008/01/boost-tokenizer.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3829096759039124721/posts/default/6303019342757800907'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3829096759039124721/posts/default/6303019342757800907'/><link rel='alternate' type='text/html' href='http://codeblog.zhengzhong.net/2008/01/boost-tokenizer.html' title='Boost Tokenizer笔记'/><author><name>Zhong ZHENG</name><uri>https://profiles.google.com/106629979370891920105</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-uEokg-47neM/AAAAAAAAAAI/AAAAAAAADs8/WCNYNlWPrFk/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3829096759039124721.post-7286174764099810634</id><published>2008-01-05T05:36:00.000-08:00</published><updated>2009-03-08T11:55:36.491-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='cplusplus'/><title type='text'>Pimpl的const成员函数</title><content type='html'>先给一个pimpl的例子：&lt;br /&gt;&lt;br /&gt;&lt;pre class="prettyprint lang-cpp"&gt;////////////////////////////////////////////////////////////&lt;br /&gt;// person.hpp: pimpl class header file.&lt;br /&gt;//&lt;br /&gt;&lt;br /&gt;#include &amp;lt;string&amp;gt;&lt;br /&gt;&lt;br /&gt;class person {&lt;br /&gt;&lt;br /&gt;public:&lt;br /&gt;  explicit person();&lt;br /&gt;  ~person();&lt;br /&gt;  const std::string&amp;amp; first_name() const;&lt;br /&gt;  const std::string&amp;amp; last_name() const;&lt;br /&gt;  void set_name(const std::string&amp;amp; first_name,&lt;br /&gt;                const std::string&amp;amp; last_name);&lt;br /&gt;&lt;br /&gt;private:&lt;br /&gt;  struct impl;  // forward declaration.&lt;br /&gt;  impl* pimpl_; // pointer to impl.&lt;br /&gt;}; // class person&lt;br /&gt;&lt;br /&gt;////////////////////////////////////////////////////////////&lt;br /&gt;// person.cpp: pimpl class source file.&lt;br /&gt;//&lt;br /&gt;&lt;br /&gt;#include "person.hpp"&lt;br /&gt;#include &amp;lt;string&amp;gt;&lt;br /&gt;&lt;br /&gt;struct person::impl {&lt;br /&gt;  std::string first_name_;&lt;br /&gt;  std::string last_name_;&lt;br /&gt;  explicit impl(): first_name_(), last_name() {&lt;br /&gt;    // Do nothing.&lt;br /&gt;  }&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;person::person(): pimpl_(new impl()) {&lt;br /&gt;  // Do nothing.&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;person::~person() {&lt;br /&gt;  delete pimpl_;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;const std::string&amp;amp; person::first_name() const {&lt;br /&gt;  return pimpl_-&amp;gt;first_name_;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;const std::string&amp;amp; person::last_name() const {&lt;br /&gt;  return pimpl_-&amp;gt;last_name_;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;void person::set_name(const std::string&amp;amp; first_name,&lt;br /&gt;                      const std::string&amp;amp; last_name) {&lt;br /&gt;  pimpl_-&amp;gt;first_name_ = first_name;&lt;br /&gt;  pimpl_-&amp;gt;last_name_  = last_name;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;注意person类的两个const成员函数first_name()和last_name()，因为被标记为const，所以这两个成员函数应该不能修改person对象的内部状态。&lt;br /&gt;&lt;br /&gt;在C++中，每一个成员函数都拥有一个隐含的参数，即指向对象的this指针。对于一个const成员函数，this是一个被const了的指针。在没有使用pimpl的时候，如果我们试图（通过const的this指针）修改对象的状态，将产生一个编译错误。在这种情况下，编译器很体贴地帮我们保证了const成员函数语义的正确性。&lt;br /&gt;&lt;br /&gt;可是注意，当我们使用了pimpl的时候，我们就失去了编译器这样的关怀。假设我们这样实现first_name()成员函数：&lt;br /&gt;&lt;br /&gt;&lt;pre class="prettyprint lang-cpp"&gt;// Const member function is no longer that "const"...&lt;br /&gt;const std::string&amp;amp; person::first_name() const {&lt;br /&gt;  pimpl_-&amp;gt;first_name_ = "Whatever"; // Note this assignment!&lt;br /&gt;  return pimpl_-&amp;gt;first_name_;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;这段代码可以很顺利地通过编译，连一个警告都不会有。为什么？因为对于一个指向const person类型的this指针，它const的其实是pimpl_指针的地址，而不是pimpl_所指向的那个对象。也就是说，编译器只能帮我们保证在实现person的const成员函数的时候无法修改pimpl_的地址值，却无法为我们保证我们不去修改pimpl_所指向的person::impl对象的内容。&lt;br /&gt;&lt;br /&gt;失去了编译器的检查，就增加了我们写出语义错误的代码的可能性。对此，我们可以通过如下的规范来重新获得编译器的这种关怀。&lt;br /&gt;&lt;br /&gt;第一，在person.hpp头文件中为person类增加两个private成员函数，如下：&lt;br /&gt;&lt;br /&gt;&lt;pre class="prettyprint lang-cpp"&gt;////////////////////////////////////////////////////////////&lt;br /&gt;// person.hpp: pimpl class header file.&lt;br /&gt;//&lt;br /&gt;&lt;br /&gt;class person {&lt;br /&gt;&lt;br /&gt;  // ...&lt;br /&gt;&lt;br /&gt;private:&lt;br /&gt;  struct impl; // forward declaration.&lt;br /&gt;  const impl* pimpl() const {&lt;br /&gt;    return pimpl_;&lt;br /&gt;  }&lt;br /&gt;  impl* pimpl() {&lt;br /&gt;    return pimpl_;&lt;br /&gt;  }&lt;br /&gt;  impl* pimpl_;&lt;br /&gt;};&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;第二，在实现person的成员函数时，每当我们需要使用pimpl_指针，总是通过调用pimpl()成员函数来获得：&lt;br /&gt;&lt;br /&gt;&lt;pre class="prettyprint lang-cpp"&gt;////////////////////////////////////////////////////////////&lt;br /&gt;// person.cpp: pimpl class source file.&lt;br /&gt;//&lt;br /&gt;&lt;br /&gt;// ...&lt;br /&gt;&lt;br /&gt;const std::string&amp;amp; person::first_name() const {&lt;br /&gt;  // Won't compile any more if we keep using pimpl().&lt;br /&gt;  // pimpl()-&amp;gt;first_name_ = "Whatever";&lt;br /&gt;  return pimpl()-&amp;gt;first_name_;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;const std::string&amp;amp; person::last_name() const {&lt;br /&gt;  return pimpl()-&amp;gt;last_name_;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;void person::set_name(const std::string&amp;amp; first_name,&lt;br /&gt;                      const std::string&amp;amp; last_name) {&lt;br /&gt;  pimpl()-&amp;gt;first_name_ = first_name;&lt;br /&gt;  pimpl()-&amp;gt;last_name_  = last_name;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3829096759039124721-7286174764099810634?l=codeblog.zhengzhong.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeblog.zhengzhong.net/feeds/7286174764099810634/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://codeblog.zhengzhong.net/2008/01/pimplconst-member-function.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3829096759039124721/posts/default/7286174764099810634'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3829096759039124721/posts/default/7286174764099810634'/><link rel='alternate' type='text/html' href='http://codeblog.zhengzhong.net/2008/01/pimplconst-member-function.html' title='Pimpl的const成员函数'/><author><name>Zhong ZHENG</name><uri>https://profiles.google.com/106629979370891920105</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-uEokg-47neM/AAAAAAAAAAI/AAAAAAAADs8/WCNYNlWPrFk/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3829096759039124721.post-8950310672581448396</id><published>2008-01-02T05:50:00.000-08:00</published><updated>2009-03-08T11:46:37.047-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='未完成'/><category scheme='http://www.blogger.com/atom/ns#' term='cplusplus'/><category scheme='http://www.blogger.com/atom/ns#' term='boost'/><title type='text'>Boost Multi-index笔记</title><content type='html'>&lt;big&gt;&lt;b&gt;Boost Multi-index介绍&lt;/b&gt;&lt;/big&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;注意：&lt;/b&gt; 为了在MSVC7.1下顺利编译boost multi-index，需要关掉/Gm选项（C/C++ | Code Generation | Enable Minimal Rebuild）。否则可能会产生Buffer Overrun错误。详情请参考&lt;a href="http://www.boost.org/libs/multi_index/doc/index.html"&gt;Boost Multi-index文档&lt;/a&gt;。&lt;br /&gt;&lt;br /&gt;不同的STL容器用不同的方法来管理自己的元素，提供不同的访问元素的方法。比如，std::set通过一个比较函数来为元素排序，std::list则允许用户自由地制定插入元素的位置。某些情况下，对于同一个元素集合，用户会希望拥有不同的访问接口，这有点类似于MVC模式中的Model和View：同一个Model拥有不同的View。Boost multi-index就是用来满足这样的需求的。&lt;br /&gt;&lt;br /&gt;举例说明。比如我创建了一个Employee类来为公司员工建模：&lt;br /&gt;&lt;br /&gt;&lt;pre class="prettyprint lang-cpp"&gt;#include &amp;lt;string&amp;gt;&lt;br /&gt;#include &amp;lt;iostream&amp;gt;&lt;br /&gt;&lt;br /&gt;//! The employee class...&lt;br /&gt;class employee {&lt;br /&gt;&lt;br /&gt;public:&lt;br /&gt;&lt;br /&gt;  //! Default constructor.&lt;br /&gt;  explicit employee(): id_(), email_(), name_() {&lt;br /&gt;    // Do nothing.&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  explicit employee(const std::string&amp;amp; id,&lt;br /&gt;                    const std::string&amp;amp; email,&lt;br /&gt;                    const std::string&amp;amp; name)&lt;br /&gt;  : id_(id), email_(email), name_(name) {&lt;br /&gt;    // Do nothing.&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  // Use auto-generated copy constructor.&lt;br /&gt;  // Use auto-generated copy assignment.&lt;br /&gt;  // Use auto-generated destructor.&lt;br /&gt;&lt;br /&gt;  bool operator&amp;lt;(const employee&amp;amp; rhs) const {&lt;br /&gt;    return (id_ &amp;lt; rhs.id_);&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;public:&lt;br /&gt;&lt;br /&gt;  std::string id_;    // Unique ID.&lt;br /&gt;  std::string email_; // Unique email address.&lt;br /&gt;  std::string name_;  // Name.&lt;br /&gt;&lt;br /&gt;}; // class employee&lt;br /&gt;&lt;br /&gt;//! Writes an employee information to the output stream.&lt;br /&gt;std::ostream&amp;amp; operator&amp;lt;&amp;lt;(std::ostream&amp;amp; os,&lt;br /&gt;                         const employee&amp;amp; e) {&lt;br /&gt;  os &amp;lt;&amp;lt; "Employee #" &amp;lt;&amp;lt; e.id_&lt;br /&gt;     &amp;lt;&amp;lt; " : " &amp;lt;&amp;lt; e.name_&lt;br /&gt;     &amp;lt;&amp;lt; " ( " &amp;lt;&amp;lt; e.email_ &amp;lt;&amp;lt; " ) ";&lt;br /&gt;  return os;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;//! Compares two employees by their names.&lt;br /&gt;struct comp_name {&lt;br /&gt;  // TODO:&lt;br /&gt;};&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;我希望拥有一个员工对象的集合，该集合提供了以下几种不同的访问员工对象的方式：&lt;br /&gt;&lt;br /&gt;- 按照元素插入的顺序提供顺序访问（类似std::list）。&lt;br /&gt;- 按照employee自己的比较函数（比较id_）排序，提供顺序访问（类似std::set）。&lt;br /&gt;- 按照name_排序（使用CompName比较函数），提供顺序访问（类似std::set）。&lt;br /&gt;- 以id_为key访问对象（类似std::map）。&lt;br /&gt;- 以email_为key访问对象（类似std::map）。&lt;br /&gt;&lt;br /&gt;&lt;big&gt;&lt;b&gt;容器的模型和视图&lt;/b&gt;&lt;/big&gt;&lt;br /&gt;&lt;br /&gt;Boost multi-index中的容器模型使用boost::multi_index::multi_index_container模板类来描述，而与容器模型相联系的每个视图都由一个index类型来描述。Index类型可以被划分为以下两大类：&lt;br /&gt;&lt;br /&gt;- Unique：不允许出现拥有相同键值的两个或多个元素。&lt;br /&gt;- Non-unique：允许两个或多个元素拥有相同的键值。&lt;br /&gt;&lt;br /&gt;对应于以上的需求，可以这样定义容器的模型：&lt;br /&gt;&lt;br /&gt;&lt;pre class="prettyprint lang-cpp"&gt;namespace bmi = boost::multi_index; // namespace alias&lt;br /&gt;&lt;br /&gt;//! Typedef of the multi-index container model.&lt;br /&gt;typedef bmi::multi_index_container&amp;lt;&lt;br /&gt;  employee,        // the element type...&lt;br /&gt;  bmi::indexed_by&amp;lt; // views for this container...&lt;br /&gt;    // index #0: sequenced&lt;br /&gt;    bmi::sequenced&amp;lt;&amp;gt;,&lt;br /&gt;    // index #1: sort by employee::operator&amp;lt;&lt;br /&gt;    bmi::ordered_unique&amp;lt;bmi::identity&amp;lt;employee&amp;gt; &amp;gt;,&lt;br /&gt;    // index #2: sort by std::less&amp;lt;std::string&amp;gt; on name_&lt;br /&gt;    bmi::ordered_non_unique&amp;lt;&lt;br /&gt;      bmi::member&amp;lt;employee,&lt;br /&gt;                  std::string,&lt;br /&gt;                  &amp;amp;employee::name_&amp;gt; &amp;gt;&lt;br /&gt;  &amp;gt; // end of bmi::indexed_by&lt;br /&gt;&amp;gt; employee_set;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;对于一个employee_set容器，可以通过指定下标的方法获得不同的index视图：&lt;br /&gt;&lt;br /&gt;&lt;pre class="prettyprint lang-cpp"&gt;//! Typedef of the sequenced index.&lt;br /&gt;typedef employee_set::nth_index&amp;lt;0&amp;gt;::type sequenced_index;&lt;br /&gt;&lt;br /&gt;//! Typedef of the built-in less-than index.&lt;br /&gt;typedef employee_set::nth_index&amp;lt;1&amp;gt;::type less_than_index;&lt;br /&gt;&lt;br /&gt;//! Typedef of the name index.&lt;br /&gt;typedef employee_set::nth_index&amp;lt;2&amp;gt;::type name_index;&lt;br /&gt;&lt;br /&gt;//! Returns the sequenced index of the underlying set.&lt;br /&gt;sequenced_index&amp;amp; get_sequenced_index(employee_set&amp;amp; es) {&lt;br /&gt;  return es.get&amp;lt;0&amp;gt;(); // index #0&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;//! Returns the less-than index of the underlying set.&lt;br /&gt;less_than_index&amp;amp; get_less_than_index(employee_set&amp;amp; es) {&lt;br /&gt;  return es.get&amp;lt;1&amp;gt;(); // index #1&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;//! Returns the name index of the underlying set.&lt;br /&gt;name_index&amp;amp; get_name_index(employee_set&amp;amp; es) {&lt;br /&gt;  return es.get&amp;lt;2&amp;gt;(); // index #2&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;注意：容器模型的视图需要通过引用传递，而不可以通过值拷贝。&lt;br /&gt;&lt;br /&gt;&lt;big&gt;&lt;b&gt;使用Tag来标记Index&lt;/b&gt;&lt;/big&gt;&lt;br /&gt;&lt;br /&gt;&lt;big&gt;&lt;b&gt;容器模型自身的成员函数&lt;/b&gt;&lt;/big&gt;&lt;br /&gt;&lt;br /&gt;&lt;big&gt;&lt;b&gt;通过Index插入元素的方法&lt;/b&gt;&lt;/big&gt;&lt;br /&gt;&lt;br /&gt;&lt;big&gt;&lt;b&gt;通过Index遍历元素的方法&lt;/b&gt;&lt;/big&gt;&lt;br /&gt;&lt;br /&gt;每个一个index视图（sequenced_index，less_than_index和name_index）都提供自己的iterator和const_iterator类型，它们按照各个视图所定义的顺序来遍历容器中的元素。以下代码演示了如何通过index的const_iterator来遍历容器中的元素：&lt;br /&gt;&lt;br /&gt;&lt;pre class="prettyprint lang-cpp"&gt;//! Iterates through all employees.&lt;br /&gt;template&amp;lt;class Index&amp;gt;&lt;br /&gt;void write_by(const Index&amp;amp; index) {&lt;br /&gt;  for (Index::const_iterator i = index.begin();&lt;br /&gt;                             i != index.end(); ++i) {&lt;br /&gt;    std::cout &amp;lt;&amp;lt; (*i) &amp;lt;&amp;lt; std::endl;&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;//! Iterates through all employees using different index.&lt;br /&gt;void test_index_iterators() {&lt;br /&gt;  // Populate employees to the container.&lt;br /&gt;  employee_set es = ...;&lt;br /&gt;  // Iterate through employees using different index.&lt;br /&gt;  write_by(get_sequenced_index(es));&lt;br /&gt;  write_by(get_less_than_index(es));&lt;br /&gt;  write_by(get_name_index(es));&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;为什么没有index提供std::vector那样的[]操作符和at()函数？在没有读过boost multi-index源代码的情况下，我的理解是：在STL中，std::vector是一种很特殊的容器，它是唯一一个使用连续内存存储元素的容器（所以它可以和C语言中的数组兼容）。由于它的这种实现方法，使得[]操作符和at()函数的实现可以非常高效。而对于任何一种其它的STL容器而言，这种随机存取的方法实现起来都太昂贵了。Boost multi-index中的容器应该没有使用连续内存来存储元素，所以它也不会提供这种随机存取元素的方法。&lt;br /&gt;&lt;br /&gt;&lt;big&gt;&lt;b&gt;通过Index查找元素的方法&lt;/b&gt;&lt;/big&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;TODO:&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;- How to insert elements.&lt;br /&gt;- How to look up elements (find).&lt;br /&gt;- How to tag an index.&lt;br /&gt;- Common functions in multi_index_container.&lt;br /&gt;- How to use customized comparator.&lt;br /&gt;- identity: should operator equals (==) be implemented?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3829096759039124721-8950310672581448396?l=codeblog.zhengzhong.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeblog.zhengzhong.net/feeds/8950310672581448396/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://codeblog.zhengzhong.net/2008/01/boostmultiindex.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3829096759039124721/posts/default/8950310672581448396'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3829096759039124721/posts/default/8950310672581448396'/><link rel='alternate' type='text/html' href='http://codeblog.zhengzhong.net/2008/01/boostmultiindex.html' title='Boost Multi-index笔记'/><author><name>Zhong ZHENG</name><uri>https://profiles.google.com/106629979370891920105</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-uEokg-47neM/AAAAAAAAAAI/AAAAAAAADs8/WCNYNlWPrFk/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3829096759039124721.post-6237582306805249872</id><published>2007-11-28T07:39:00.001-08:00</published><updated>2009-03-08T11:34:11.019-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='cplusplus'/><title type='text'>C++ Coding Conventions</title><content type='html'>&lt;i&gt;It is easier to write an incorrect program than understand a correct one.&lt;br /&gt;-- &lt;a href="http://en.wikipedia.org/wiki/Alan_J._Perlis"&gt;Alan J. Perlis&lt;/a&gt;&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;big&gt;&lt;b&gt;Contents&lt;/b&gt;&lt;/big&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="#Preface"&gt;0. Preface&lt;/a&gt;&lt;br /&gt;&lt;a href="#Indentation"&gt;1. Indentation&lt;/a&gt;&lt;br /&gt;&lt;a href="#Comments"&gt;2. Comments&lt;/a&gt;&lt;br /&gt;&lt;a href="#NamingConventions"&gt;3. Naming Conventions&lt;/a&gt;&lt;br /&gt;&lt;a href="#TheEnd"&gt;4. The End&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a name="Preface" id="Preface"&gt;&lt;/a&gt;&lt;big&gt;&lt;b&gt;0. Preface&lt;/b&gt;&lt;/big&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;How Strict Are These Standards&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;The goal of this document is to define a set of coding conventions that may help developers write human-readable C++ code. The conventions may be classified into the following 3 categories:&lt;br /&gt;&lt;br /&gt;1. Must and must not: these are important rules that must be strictly respected without exception.&lt;br /&gt;2. Should and should not: these are also important rules. They are usually the right (or wrong) way. Developers should try their best to respect them unless they really have a good reason.&lt;br /&gt;3. Alternatives: all alternatives listed in this document are acceptable. Developers may choose one of them to apply.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Basic Rules&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;1. All should be as understandable as possible.&lt;br /&gt;2. All should be as readable as possible, except when it would conflict with the previous rule.&lt;br /&gt;3. All should be as simple as possible, except when it would conflict with the previous rules.&lt;br /&gt;&lt;br /&gt;&lt;a href="Indentation" id="Indentation"&gt;&lt;/a&gt;&lt;big&gt;&lt;b&gt;1. Indentation&lt;/b&gt;&lt;/big&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Line Length&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Developers must not write lines longer than 120 characters. They should keep their lines shorter than 100 or 80 charaters. Moving the bottom scrollbar hundreds of times when reading a source file is never a pleasant experience.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Indentation&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Developers must indent their code. How many spaces should be used as the unit of indentation is not enforced, but developers must keep the indentation consistent at least within one file. They should use 4 spaces as the unit of indentation (which is most widely accepted as a convention). They should use blank spaces instead of tabs (which may be 4 spaces or 8 spaces, depending on the IDE settings).&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Wrapping Lines&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;When an expression will not fit on a single line, developers should break it into multiple lines according to these general principles:&lt;br /&gt;&lt;br /&gt;1. Break after a comma.&lt;br /&gt;2. Break before an operator.&lt;br /&gt;3. Prefer higher-level breaks to lower-level breaks.&lt;br /&gt;4. Align the new line with the beginning of the expression at the same level on the previous line.&lt;br /&gt;5. If the above rules lead to confusing code or to code that's squished up against the right margin, just indent 8 spaces instead. &lt;br /&gt;&lt;br /&gt;Examples of breaking function calls:&lt;br /&gt;&lt;br /&gt;&lt;pre class="prettyprint lang-cpp"&gt;// Align the function parameters at the same level.&lt;br /&gt;my_function(long_expression_1,&lt;br /&gt;            long_expression_2,&lt;br /&gt;            long_expression_3,&lt;br /&gt;            long_expression_4,&lt;br /&gt;            long_expression_5);&lt;br /&gt;// Indent 8 spaces for the first function call to avoid&lt;br /&gt;// very deep indents, and align the parameters of the&lt;br /&gt;// second function at the same level.&lt;br /&gt;var = my_first_function(&lt;br /&gt;        long_expression_1,&lt;br /&gt;        my_second_function(long_expression_2,&lt;br /&gt;                           long_expression_3));&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Examples of breaking an arithmetic expression:&lt;br /&gt;&lt;br /&gt;&lt;pre class="prettyprint lang-cpp"&gt;// Prefer higher-level breaks to lower-level breaks, and&lt;br /&gt;// align the new line with the beginning of the expression&lt;br /&gt;// at the same level on the previous line.&lt;br /&gt;long_name_1 = long_name_2 * (long_name_3 + long_name_4)&lt;br /&gt;            + 4 * long_name_5;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Examples of long function declarations.&lt;br /&gt;&lt;br /&gt;&lt;pre class="prettyprint lang-cpp"&gt;// Align the function parameters at the same level.&lt;br /&gt;void my_function(int first_param,&lt;br /&gt;                 my_type another_param,&lt;br /&gt;                 const std::string&amp;amp; yet_another,&lt;br /&gt;                 const my_second_type* and_still_another);&lt;br /&gt;// Indent 8 spaces to avoid very deep indents.&lt;br /&gt;std::string my_function_with_a_terriblly_long_name(&lt;br /&gt;        int first_param,&lt;br /&gt;        my_type another_param,&lt;br /&gt;        const std::string&amp;amp; yet_another,&lt;br /&gt;        const my_second_type* and_still_another);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Examples of class/function declarations with templates:&lt;br /&gt;&lt;br /&gt;&lt;pre class="prettyprint lang-cpp"&gt;// Align the class template parameters at the same level.&lt;br /&gt;template &amp;lt;typename SomeType,&lt;br /&gt;          typename AnotherType,&lt;br /&gt;          typename YetAnotherType,&lt;br /&gt;          typename AndStillAnother&amp;gt;&lt;br /&gt;class my_class_template {&lt;br /&gt;    // ...&lt;br /&gt;};&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Blank Spaces&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Binary operators should be separated from their operands by spaces. Unary operators, such as unary minus, increment (++), and decrement (--), should not be separated from their operands. Examples:&lt;br /&gt;&lt;br /&gt;&lt;pre class="prettyprint lang-cpp"&gt;&lt;br /&gt;a = (a + b) / (c * d);a += c + d;a++;&lt;br /&gt;std::cout &amp;lt;&amp;lt; "size is " &amp;lt;&amp;lt; size &amp;lt;&amp;lt; std::endl;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;When declaring or calling a function with multiple parameters, developers must use a blank space to separate the parameters. Examples:&lt;br /&gt;&lt;br /&gt;&lt;pre class="prettyprint lang-cpp"&gt;my_function(param_1, param_2, param_3);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="Comments" id="Comments"&gt;&lt;/a&gt;&lt;big&gt;&lt;b&gt;2. Comments&lt;/b&gt;&lt;/big&gt;&lt;br /&gt;&lt;br /&gt;Developers should use // ... instead of /* ... */ when commenting their code. This makes it easier to comment out a block of code when debugging.&lt;br /&gt;&lt;br /&gt;Developers must write doxygen comments for public APIs (classes, functions, enumerations, typedefs, etc.) that are easy to be misused. Developers should write doxygen comments whenever necessary. The doxygen comment format is not enforced.&lt;br /&gt;&lt;br /&gt;For more information about doxygen, check the doxygen project website at &lt;a href="http://www.doxygen.org/"&gt;http://www.doxygen.org/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Examples of one recommended doxygen comment style:&lt;br /&gt;&lt;br /&gt;&lt;pre class="prettyprint lang-cpp"&gt;&lt;br /&gt;//! Documentation of this class: what does this class&lt;br /&gt;//! modelize; how should this class be used, etc.&lt;br /&gt;class some_class {&lt;br /&gt;&lt;br /&gt;public:&lt;br /&gt;&lt;br /&gt;    //! Documentation of this function. Don't write comment&lt;br /&gt;    //! to repeat code. Write something that helps the users&lt;br /&gt;    //! better understand how to use this function correctly.&lt;br /&gt;    //! \param param_1  description of the first parameter.&lt;br /&gt;    //! \param param_2  description of the second parameter.&lt;br /&gt;    //! \return describe the return value.&lt;br /&gt;    //! \throws first_exception   describe when the first&lt;br /&gt;    //!         exception will be thrown out.&lt;br /&gt;    //! \throws second_exception  describe when the second&lt;br /&gt;    //!         exception will be thrown out.&lt;br /&gt;    int my_func(int param_1, const&amp;amp; std::string param_2);&lt;br /&gt;&lt;br /&gt;private:&lt;br /&gt;&lt;br /&gt;    int member1_; //!&amp;lt; Description of the first member.&lt;br /&gt;    int member2_; //!&amp;lt; Description of the second member.&lt;br /&gt;    &lt;br /&gt;    //! If the description of this member is enough to&lt;br /&gt;    //! occupy multiple lines, then this form of comment is&lt;br /&gt;    //! also perfectly acceptable.&lt;br /&gt;    int member3_;&lt;br /&gt;&lt;br /&gt;}; // class some_class&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;a name="NamingConventions" id="NamingConventions"&gt;&lt;/a&gt;&lt;big&gt;&lt;b&gt;3. Naming Conventions&lt;/b&gt;&lt;/big&gt;&lt;br /&gt;&lt;br /&gt;First of all, some general guidelines for names:&lt;br /&gt;&lt;br /&gt;1. All names (class names, identifier names, etc.), as well as the rest of the code and comments, must be written in English.&lt;br /&gt;2. All user-defined names must not start with an underscore. Some underscored names are reserved by the compiler. Using such kind of names may have potential danger of name conflicts.&lt;br /&gt;3. Do NOT use &lt;a href="http://en.wikipedia.org/wiki/Hungarian_notation"&gt;Hungarian notation&lt;/a&gt; in C++.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;underscored_names and CamelCase&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;The following styles are commonly used to write a name consisting of compounded words or phrases:&lt;br /&gt;&lt;br /&gt;- write_all_words_in_lower_case_and_join_them_using_underscores.&lt;br /&gt;- IndicateWordBoundariesUsingCapitalization. This style has two variants: lowerCamelCase and UpperCamelCase.&lt;br /&gt;&lt;br /&gt;The STL/boost style uses underscored_names, while the Java style and Microsoft style use CamelCase heavily. All these styles are acceptable, but developers must keep the naming convention consistent at least within one project.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Namespaces&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;To name a namespace:&lt;br /&gt;&lt;br /&gt;- STL/boost style uses underscored_names.&lt;br /&gt;- Java style uses lowerCamelCase.&lt;br /&gt;- Microsoft style uses UpperCamelCase.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Type Names&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Types define the classification of variables. A type may be an enumeration, a typedef, a class, or a struct. To name a type:&lt;br /&gt;&lt;br /&gt;- STL/boost style uses underscored_names.&lt;br /&gt;- both Java style and Microsoft style use UpperCamelCase.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Function Names&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;To name a function (at global level or at class level):&lt;br /&gt;&lt;br /&gt;- STL/boost style uses underscored_names.&lt;br /&gt;- Java style uses lowerCamelCase.&lt;br /&gt;- Microsoft style uses UpperCamelCase.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Identifier Names&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;To name a variable or a function parameter:&lt;br /&gt;&lt;br /&gt;- STL/boost style uses underscored_names.&lt;br /&gt;- both Java style and Microsoft style use lowerCamelCase.&lt;br /&gt;&lt;br /&gt;Variables, except when inside a loop, must not be named using a single character. Variables inside a loop may be named as i, j, k, m, or n.&lt;br /&gt;&lt;br /&gt;Some additional conventions should be applied to name a member variable within a class or a struct:&lt;br /&gt;&lt;br /&gt;- add an 'm_' prefix for non-static member variables, and add an 's_' prefix for static member variables.&lt;br /&gt;- add an underscore suffix for all member variables (static or non-static).&lt;br /&gt;&lt;br /&gt;Both the two alternatives are acceptable, but the convention must be consistent within one project.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Template Parameter Names&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Developers must use UpperCamelCase to name template parameters. It is recommended that developers use pithy (single charactoer if possible) yet evocative names for template parameter names. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;Constants and Macros&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Constants and macros must be named using UPPER_CASES_WITH_UNDERSCORES. In addition, all macros within a project must be prefixed by the project's name and an underscore. It is recommended that guard macros (which prevent recursive inclusion of header files) be named using the pattern &amp;lt;PROJECT_NAME&amp;gt;_&amp;lt;HEADER_FILE_NAME&amp;gt;_&amp;lt;CREATED_DATE&amp;gt;__. This pattern helps distinguish guard macros from other macros.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Examples&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;STL/boost style:&lt;br /&gt;&lt;br /&gt;&lt;pre class="prettyprint lang-cpp"&gt;// my_zoo.hpp: STL/boost style&lt;br /&gt;#ifndef MYPROJ_MY_ZOO_HPP_20071128__&lt;br /&gt;#define MYPROJ_MY_ZOO_HPP_20071128__&lt;br /&gt;&lt;br /&gt;#define MYPROJ_LOGGING_ENABLED 1&lt;br /&gt;&lt;br /&gt;namespace my_proj {&lt;br /&gt;&lt;br /&gt;    typedef enum {&lt;br /&gt;        tigar,&lt;br /&gt;        elephant,&lt;br /&gt;        lion,&lt;br /&gt;        monkey,&lt;br /&gt;    } animal_race;&lt;br /&gt;&lt;br /&gt;    class animal {&lt;br /&gt;&lt;br /&gt;    public:&lt;br /&gt;        explicit animal(const std::string&amp;amp; name);&lt;br /&gt;        virtual ~animal() = 0;&lt;br /&gt;        const std::string&amp;amp; name() const;&lt;br /&gt;        animal_race race() const;&lt;br /&gt;        virtual void eat() = 0;&lt;br /&gt;&lt;br /&gt;    private:&lt;br /&gt;        std::string name_;&lt;br /&gt;        animal_race race_;&lt;br /&gt;&lt;br /&gt;    }; // class animal&lt;br /&gt;&lt;br /&gt;    class my_zoo {&lt;br /&gt;&lt;br /&gt;        typedef std::map&amp;lt;std::string, animal*&amp;gt; container_type;&lt;br /&gt;&lt;br /&gt;    public:&lt;br /&gt;&lt;br /&gt;        explicit my_zoo();&lt;br /&gt;        void add(animal* the_animal);&lt;br /&gt;&lt;br /&gt;        template&amp;lt;class T&amp;gt;&lt;br /&gt;        T* find(const std::string&amp;amp; name) {&lt;br /&gt;            animal* the_animal = find_animal(name);&lt;br /&gt;            return dynamic_cast&amp;lt;T*&amp;gt;(the_animal);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;    private:&lt;br /&gt;&lt;br /&gt;        animal* find_animal(const std::string&amp;amp; name);&lt;br /&gt;&lt;br /&gt;    private:&lt;br /&gt;&lt;br /&gt;        container_type animals_in_zoo_;&lt;br /&gt;&lt;br /&gt;    }; // class my_zoo&lt;br /&gt;&lt;br /&gt;} // namespace my_proj&lt;br /&gt;&lt;br /&gt;#endif // MYPROJ_MY_ZOO_HPP_20071128__&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Java style:&lt;br /&gt;&lt;br /&gt;&lt;pre class="prettyprint lang-cpp"&gt;// MyZoo.hpp: Java style&lt;br /&gt;#ifndef MYPROJ_MY_ZOO_HPP_20071128__&lt;br /&gt;#define MYPROJ_MY_ZOO_HPP_20071128__&lt;br /&gt;&lt;br /&gt;#define MYPROJ_LOGGING_ENABLED 1&lt;br /&gt;&lt;br /&gt;namespace myProj {&lt;br /&gt;&lt;br /&gt;    typedef enum {&lt;br /&gt;        TIGAR,&lt;br /&gt;        ELEPHANT,&lt;br /&gt;        LION,&lt;br /&gt;        MONKEY,&lt;br /&gt;    } AnimalRace;&lt;br /&gt;&lt;br /&gt;    class Animal {&lt;br /&gt;&lt;br /&gt;    public:&lt;br /&gt;        explicit Animal(const std::string&amp;amp; name);&lt;br /&gt;        virtual ~Animal() = 0;&lt;br /&gt;        const std::string&amp;amp; getName() const;&lt;br /&gt;        AnimalRace getRace() const;&lt;br /&gt;        virtual void eat() = 0;&lt;br /&gt;&lt;br /&gt;    private:&lt;br /&gt;        std::string name_;&lt;br /&gt;        AnimalRace  race_;&lt;br /&gt;&lt;br /&gt;    }; // class Animal&lt;br /&gt;&lt;br /&gt;    class MyZoo {&lt;br /&gt;&lt;br /&gt;        typedef std::map&amp;lt;std::string, Animal*&amp;gt; ContainerType;&lt;br /&gt;&lt;br /&gt;    public:&lt;br /&gt;&lt;br /&gt;        explicit MyZoo();&lt;br /&gt;        void add(Animal* animal);&lt;br /&gt;&lt;br /&gt;        template&amp;lt;class T&amp;gt;&lt;br /&gt;        T* find(const std::string&amp;amp; name) {&lt;br /&gt;            Animal* animal = findAnimal(name);&lt;br /&gt;            return dynamic_cast&amp;lt;T*&amp;gt;(animal);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;    private:&lt;br /&gt;&lt;br /&gt;        Animal* findAnimal(const std::string&amp;amp; name);&lt;br /&gt;&lt;br /&gt;    private:&lt;br /&gt;&lt;br /&gt;        ContainerType animalsInZoo_;&lt;br /&gt;&lt;br /&gt;    }; // class MyZoo&lt;br /&gt;&lt;br /&gt;} // namespace myProj&lt;br /&gt;&lt;br /&gt;#endif // MYPROJ_MY_ZOO_HPP_20071128__&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Microsoft style:&lt;br /&gt;&lt;br /&gt;&lt;pre class="prettyprint lang-cpp"&gt;// MyZoo.hpp: Microsoft style&lt;br /&gt;#ifndef MYPROJ_MY_ZOO_HPP_20071128__&lt;br /&gt;#define MYPROJ_MY_ZOO_HPP_20071128__&lt;br /&gt;&lt;br /&gt;#define MYPROJ_LOGGING_ENABLED 1&lt;br /&gt;&lt;br /&gt;namespace MyProj {&lt;br /&gt;&lt;br /&gt;    typedef enum {&lt;br /&gt;        TIGAR,&lt;br /&gt;        ELEPHANT,&lt;br /&gt;        LION,&lt;br /&gt;        MONKEY,&lt;br /&gt;    } AnimalRace;&lt;br /&gt;&lt;br /&gt;    class Animal {&lt;br /&gt;&lt;br /&gt;    public:&lt;br /&gt;        explicit Animal(const std::string&amp;amp; name);&lt;br /&gt;        virtual ~Animal() = 0;&lt;br /&gt;        const std::string&amp;amp; GetName() const;&lt;br /&gt;        AnimalRace GetRace() const;&lt;br /&gt;        virtual void Eat() = 0;&lt;br /&gt;&lt;br /&gt;    private:&lt;br /&gt;        std::string name_;&lt;br /&gt;        AnimalRace  race_;&lt;br /&gt;    }; // class Animal&lt;br /&gt;&lt;br /&gt;    class MyZoo {&lt;br /&gt;&lt;br /&gt;        typedef std::map&amp;lt;std::string, Animal*&amp;gt; ContainerType;&lt;br /&gt;&lt;br /&gt;    public:&lt;br /&gt;&lt;br /&gt;        explicit MyZoo();&lt;br /&gt;        void Add(Animal* animal);&lt;br /&gt;&lt;br /&gt;        template&amp;lt;class T&amp;gt;&lt;br /&gt;        T* Find(const std::string&amp;amp; name) {&lt;br /&gt;            Animal* animal = FindAnimal(name);&lt;br /&gt;            return dynamic_cast&amp;lt;T*&amp;gt;(animal);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;    private:&lt;br /&gt;&lt;br /&gt;        Animal* FindAnimal(const std::string&amp;amp; name);&lt;br /&gt;&lt;br /&gt;    private:&lt;br /&gt;&lt;br /&gt;        ContainerType animalsInZoo_;&lt;br /&gt;&lt;br /&gt;    }; // class MyZoo&lt;br /&gt;&lt;br /&gt;} // namespace MyProj&lt;br /&gt;&lt;br /&gt;#endif // MYPROJ_MY_ZOO_HPP_20071128__&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Personally, I prefere the STL/boost style. Because I use heavily STL and boost in my projects, using the same convention makes my code look consistent.&lt;br /&gt;&lt;br /&gt;&lt;a name="TheEnd" id="TheEnd"&gt;&lt;/a&gt;&lt;big&gt;&lt;b&gt;4. The End&lt;/b&gt;&lt;/big&gt;&lt;br /&gt;&lt;br /&gt;这份文档的第一个版本是我2006年6月刚到新公司的时候奉命起草的。那个时候我刚刚离开Java阵营，还拥有一个Java程序员应有的循规蹈距。一年半以后的今天当我重看这份文档的时候，我早已习惯了C++的放荡，因此对文档中的很多限制连我自己都觉得不爽。Java程序员是一群忠厚老实的家犬，而C++程序员却是一群桀骜不驯的野猫。这是一份修改过的版本，贴在这里纪念我由狗到猫的转变。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3829096759039124721-6237582306805249872?l=codeblog.zhengzhong.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeblog.zhengzhong.net/feeds/6237582306805249872/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://codeblog.zhengzhong.net/2007/11/c-coding-conventions.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3829096759039124721/posts/default/6237582306805249872'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3829096759039124721/posts/default/6237582306805249872'/><link rel='alternate' type='text/html' href='http://codeblog.zhengzhong.net/2007/11/c-coding-conventions.html' title='C++ Coding Conventions'/><author><name>Zhong ZHENG</name><uri>https://profiles.google.com/106629979370891920105</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-uEokg-47neM/AAAAAAAAAAI/AAAAAAAADs8/WCNYNlWPrFk/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3829096759039124721.post-5361357384031555920</id><published>2006-11-21T11:39:00.001-08:00</published><updated>2009-03-08T11:11:16.419-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='sandbox'/><title type='text'>Rendering Test / 渲染测试</title><content type='html'>This post is for rendering test...&lt;br /&gt;&lt;br /&gt;&lt;big&gt;&lt;b&gt;Test Fonts&lt;/b&gt;&lt;/big&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Bold/粗体&lt;/b&gt;, &lt;code&gt;typewriter/等宽字体&lt;/code&gt;, &lt;i&gt;italic/斜体&lt;/i&gt;, &lt;big&gt;big/大一点的字体&lt;/big&gt; and &lt;small&gt;small/小一点的字体&lt;/small&gt;.&lt;br /&gt;&lt;br /&gt;&lt;big&gt;&lt;b&gt;测试一下中文&lt;/b&gt;&lt;/big&gt;&lt;br /&gt;&lt;br /&gt;归去来兮，田园将芜胡不归！既自以心为形役，奚惆怅而独悲。悟已往之不谏，知来者之可追。实迷途其未远，觉今是而昨非。&lt;br /&gt;&lt;br /&gt;舟遥遥以轻飏，风飘飘而吹衣。问征夫以前路。恨晨光之熹微。乃瞻衡宇，载欣载奔。僮仆欢迎，稚子候门。三经就荒，松菊犹存。携幼入室，有酒盈樽。引壶觞以自酌，眄庭柯以怡颜。倚南窗以寄傲，审容膝之易安。园日涉以成趣，门虽庙而常关。策扶老以流憩，时矫首而遐观。云无心以出岫，鸟倦飞而知还。景翳翳以将入，抚孤松而盘桓。&lt;br /&gt;&lt;br /&gt;归去来兮，请息交以绝游。世与我而相违，复驾言兮焉求！悦亲戚之情话，乐琴书以消忧。农人告余以春及，将有事于西畴。或命巾车，或棹孤舟。既窈窕以寻壑，亦崎岖而经丘。木欣欣以向荣，泉涓涓而始流。善万物之得时，感吾生之行休。&lt;br /&gt;&lt;br /&gt;已矣乎，寓形宇内复几时，曷不委心任去留，胡为乎遑遑欲何之？富贵非吾愿，帝乡不可期。怀良辰以孤往，或植杖而耘籽。登东皋以舒啸，临清流而赋诗。聊乘化以归尽，乐夫天命复奚疑！&lt;br /&gt;&lt;br /&gt;-- &lt;a href="http://zh.wikipedia.org/wiki/%E9%99%B6%E6%B8%8A%E6%98%8E"&gt;陶潜&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;big&gt;&lt;b&gt;Hello, World!&lt;/b&gt;&lt;/big&gt;&lt;br /&gt;&lt;br /&gt;From &lt;a href="http://en.wikipedia.org/wiki/Hello_world"&gt;Wikipedia&lt;/a&gt;, the free encyclopedia.&lt;br /&gt;&lt;br /&gt;A &lt;b&gt;"hello world" program&lt;/b&gt; is a computer program that prints out "Hello, world!" on a display device. It is used in many introductory tutorials for teaching a programming language. Such a program is typically one of the simplest programs possible in a computer language. Some are surprisingly complex, especially in some graphical user interface (GUI) contexts, but most are very simple, especially those which rely heavily on a particular command line interpreter ("shell") to perform the actual output.&lt;br /&gt;&lt;br /&gt;While small test programs existed since the development of programmable computers, the tradition of using the phrase "Hello world!" as a test message was influenced by an example program in the book &lt;i&gt;The C Programming Language&lt;/i&gt;. The example program from that book prints "hello, world" (without capital letters or exclamation mark), and was inherited from a 1974 Bell Laboratories internal memorandum by Brian Kernighan, &lt;i&gt;Programming in C: A Tutorial&lt;/i&gt;, which contains the first known version:&lt;br /&gt;&lt;br /&gt;&lt;pre class="prettyprint lang-c"&gt;/* hello world in C */&lt;br /&gt;main() {&lt;br /&gt;  printf("hello, world");&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Hello World in C++, Python and Java&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;The following source code fragments are highlighted by &lt;a href="http://google-code-prettify.googlecode.com"&gt;Google Code Prettify&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;The C++ version:&lt;br /&gt;&lt;br /&gt;&lt;pre class="prettyprint lang-cpp"&gt;// hello world in C++&lt;br /&gt;#include &amp;lt;iostream&amp;gt;&lt;br /&gt;int main(int, char**) {&lt;br /&gt;  std::cout &amp;lt;&amp;lt; "hello, world" &amp;lt;&amp;lt; std::endl;&lt;br /&gt;  return 0;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The Python version:&lt;br /&gt;&lt;br /&gt;&lt;pre class="prettyprint lang-py"&gt;#!/usr/bin/env python&lt;br /&gt;# hello world in Python&lt;br /&gt;&lt;br /&gt;def main():&lt;br /&gt;  print 'hello, world'&lt;br /&gt;&lt;br /&gt;if __name__ == '__main__':&lt;br /&gt;  main()&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The Java version:&lt;br /&gt;&lt;br /&gt;&lt;pre class="prettyprint lang-java"&gt;// hello world in Java&lt;br /&gt;public class HelloWorld {&lt;br /&gt;  public static void main(String[] args) {&lt;br /&gt;    System.out.println("hello, world");&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;big&gt;&lt;b&gt;Test Image&lt;/b&gt;&lt;/big&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://picasaweb.google.com/heavyzheng/Personal/photo?authkey=SyhLG1vUnOY#5147467174201664226"&gt;&lt;img src="http://lh5.google.com/heavyzheng/R296H1tGIuI/AAAAAAAAAxQ/W1OwFWUohGU/s400/VanGogh_StarryNight.jpg" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3829096759039124721-5361357384031555920?l=codeblog.zhengzhong.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codeblog.zhengzhong.net/feeds/5361357384031555920/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://codeblog.zhengzhong.net/2006/11/test.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3829096759039124721/posts/default/5361357384031555920'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3829096759039124721/posts/default/5361357384031555920'/><link rel='alternate' type='text/html' href='http://codeblog.zhengzhong.net/2006/11/test.html' title='Rendering Test / 渲染测试'/><author><name>Zhong ZHENG</name><uri>https://profiles.google.com/106629979370891920105</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh6.googleusercontent.com/-uEokg-47neM/AAAAAAAAAAI/AAAAAAAADs8/WCNYNlWPrFk/s512-c/photo.jpg'/></author><thr:total>2</thr:total></entry></feed>
