﻿<?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++博客-iniwf-随笔分类-C&amp;C++</title><link>http://www.cppblog.com/iniwf/category/9821.html</link><description /><language>zh-cn</language><lastBuildDate>Thu, 19 Mar 2009 05:09:32 GMT</lastBuildDate><pubDate>Thu, 19 Mar 2009 05:09:32 GMT</pubDate><ttl>60</ttl><item><title>利用引用计数在多线程中安全释放资源</title><link>http://www.cppblog.com/iniwf/archive/2009/03/18/77036.html</link><dc:creator>iniwf</dc:creator><author>iniwf</author><pubDate>Wed, 18 Mar 2009 09:11:00 GMT</pubDate><guid>http://www.cppblog.com/iniwf/archive/2009/03/18/77036.html</guid><wfw:comment>http://www.cppblog.com/iniwf/comments/77036.html</wfw:comment><comments>http://www.cppblog.com/iniwf/archive/2009/03/18/77036.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/iniwf/comments/commentRss/77036.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/iniwf/services/trackbacks/77036.html</trackback:ping><description><![CDATA[转自<a href="http://blog.csdn.net/SeaWave/archive/2006/05/21/747863.aspx">http://blog.csdn.net/SeaWave/archive/2006/05/21/747863.aspx</a><br><br>
<div class=indent2char>本文是观大宝SODME的BLOG中文章有感，原文中提到了两种方法（对数据缓冲区使用引用计数机制、在clientsock的对象设计机制上使释放操作线性化），但只讨论了第2种方法的实现。其实在多线程程序里，要让一个释放操作线性化，并不是一件容易的事情，这不仅仅是多个IOCP工作线程的问题（一般来说，我们会为每个CPU设立两个IOCP工作线程），还涉及到其他业务逻辑线程的问题。</div>
<div class=indent2char>比方说，我们通常（就象文中也提到的）会将ClientSocket与接收缓冲区绑定到一个会话对象中（为简化起见，发送数据往往没有用overlapped机制，而是直接用一个异步send，也就不需要发送缓冲区），而这个对象可能被除IOCP工作线程以外的其他线程也用到，比方说一个事件队列的处理线程（我们会在收到数据的时候生成事件对象置入队例中，以类似于Command模式的方法来处理，而这些事件对象会引用到会话对象），或者，也许有某个容器会存放这些会话对象的一个引用，用于定时发送心跳包、会话计数、检索等等，这个时候，会话对象的销毁就不是那么简单的了，换句话说，仅靠&#8220;将销毁工作统一到执行GetQueuedCompletionStatus的函数里&#8220;是不够的。</div>
<div class=indent2char>在这种情况下，文中提到的第1种&#8220;采用引用计数&#8221;的方法就比较优雅了，在我的很多实际应用中，都是将会话对象设计为&#8220;可引用计数&#8221;的，不暴露它的析构函数，而是当引用计数减到0的时候，自动销毁，这样就保证&#8220;仅当没有任何人使用它的时候才会释放它&#8221;。 </div>
<div class=indent2char>利用C++的模板，可以十分方便地模拟出自动引用计数的安全指针：</div>
<pre class=code><font color=#000000>001:</font> <em><font color=#9a1900>/**</font></em><em><font color=#9a1900>**********************************************************************</font></em><br> <font color=#000000>002:</font> <em><font color=#9a1900>    引用计数基类、及引用计数指针模板类</font></em><br> <font color=#000000>003:</font> <em><font color=#9a1900>        －－－－NoSound QQ2591570 可随意复制、改动、使用、拍砖，概不追究！</font></em><br> <font color=#000000>004:</font> <em><font color=#9a1900>***********************************************************************</font></em><em><font color=#9a1900>*/</font></em><br> <font color=#000000>005:</font> <strong><font color=#000080>#ifndef</font></strong> _REFCOUNTED_INCLUDED_<br> <font color=#000000>006:</font> <strong><font color=#000080>#define</font></strong> _REFCOUNTED_INCLUDED_<br> <font color=#000000>007:</font> <br> <font color=#000000>008:</font> <strong><font color=#000080>#include</font></strong> <font color=#ff0000>&lt;cassert&gt;</font><br> <font color=#000000>009:</font> <strong><font color=#000080>#ifdef</font></strong> _MT<br> <font color=#000000>010:</font> <strong><font color=#000080>#include</font></strong> <font color=#ff0000>&lt;Windows.h&gt;</font><br> <font color=#000000>011:</font> <strong><font color=#000080>#endif</font></strong><br> <font color=#000000>012:</font> <br> <font color=#000000>013:</font> <strong><font color=#0000ff>class</font></strong> RefCountable <font color=#ff0000>{</font><br> <font color=#000000>014:</font> <strong><font color=#0000ff>public</font></strong><font color=#990000>:</font><br> <font color=#000000>015:</font>     <font color=#009900>int</font> <strong><font color=#000000>addRef</font></strong><font color=#990000>(</font><font color=#009900>void</font><font color=#990000>)</font> <font color=#ff0000>{</font><br> <font color=#000000>016:</font> <strong><font color=#000080>        #ifdef</font></strong> _MT<br> <font color=#000000>017:</font>         <strong><font color=#0000ff>return</font></strong> <font color=#990000>:</font><font color=#990000>:</font><strong><font color=#000000>InterlockedIncrement</font></strong><font color=#990000>(</font><font color=#990000>&amp;</font>refCount_<font color=#990000>)</font><font color=#990000>;</font><br> <font color=#000000>018:</font> <strong><font color=#000080>        #else</font></strong><br> <font color=#000000>019:</font>         <strong><font color=#0000ff>return</font></strong> <font color=#990000>+</font><font color=#990000>+</font>refCount_<font color=#990000>;</font><br> <font color=#000000>020:</font> <strong><font color=#000080>        #endif</font></strong><br> <font color=#000000>021:</font>     <font color=#ff0000>}</font><br> <font color=#000000>022:</font> <br> <font color=#000000>023:</font>     <font color=#009900>int</font> <strong><font color=#000000>decRef</font></strong><font color=#990000>(</font><font color=#009900>void</font><font color=#990000>)</font> <font color=#ff0000>{</font><br> <font color=#000000>024:</font>         <font color=#009900>int</font> r <font color=#990000>=</font><br> <font color=#000000>025:</font> <strong><font color=#000080>            #ifdef</font></strong> _MT<br> <font color=#000000>026:</font>             <font color=#990000>:</font><font color=#990000>:</font><strong><font color=#000000>InterlockedDecrement</font></strong><font color=#990000>(</font><font color=#990000>&amp;</font>refCount_<font color=#990000>)</font><font color=#990000>;</font><br> <font color=#000000>027:</font> <strong><font color=#000080>            #else</font></strong><br> <font color=#000000>028:</font>             <font color=#990000>-</font><font color=#990000>-</font>refCount_<font color=#990000>;</font><br> <font color=#000000>029:</font> <strong><font color=#000080>            #endif</font></strong><br> <font color=#000000>030:</font>         <strong><font color=#000000>assert</font></strong><font color=#990000>(</font>r<font color=#990000>&gt;</font><font color=#990000>=</font><font color=#993399>0</font><font color=#990000>)</font><font color=#990000>;</font><br> <font color=#000000>031:</font>         <strong><font color=#0000ff>if</font></strong> <font color=#990000>(</font><font color=#993399>0</font><font color=#990000>=</font><font color=#990000>=</font>r<font color=#990000>)</font><br> <font color=#000000>032:</font>             <strong><font color=#0000ff>delete</font></strong> <strong><font color=#0000ff>this</font></strong><font color=#990000>;</font><br> <font color=#000000>033:</font>         <strong><font color=#0000ff>return</font></strong> r<font color=#990000>;</font><br> <font color=#000000>034:</font>     <font color=#ff0000>}</font><br> <font color=#000000>035:</font> <br> <font color=#000000>036:</font>     <font color=#009900>int</font> <strong><font color=#000000>getRefCount</font></strong><font color=#990000>(</font><font color=#009900>void</font><font color=#990000>)</font> <strong><font color=#0000ff>const</font></strong> <font color=#ff0000>{</font> <strong><font color=#0000ff>return</font></strong> refCount_<font color=#990000>;</font> <font color=#ff0000>}</font><br> <font color=#000000>037:</font> <br> <font color=#000000>038:</font> <strong><font color=#0000ff>protected</font></strong><font color=#990000>:</font><br> <font color=#000000>039:</font>     <strong><font color=#000000>RefCountable</font></strong><font color=#990000>(</font><font color=#009900>void</font><font color=#990000>)</font> <font color=#990000>:</font> <strong><font color=#000000>refCount_</font></strong><font color=#990000>(</font><font color=#993399>0</font><font color=#990000>)</font> <font color=#ff0000>{</font><font color=#ff0000>}</font><br> <font color=#000000>040:</font>     <strong><font color=#0000ff>virtual</font></strong> <font color=#990000>~</font><strong><font color=#000000>RefCountable</font></strong><font color=#990000>(</font><font color=#009900>void</font><font color=#990000>)</font> <font color=#ff0000>{</font> <strong><font color=#000000>assert</font></strong><font color=#990000>(</font><font color=#993399>0</font><font color=#990000>=</font><font color=#990000>=</font>refCount_<font color=#990000>)</font><font color=#990000>;</font> <font color=#ff0000>}</font><br> <font color=#000000>041:</font> <br> <font color=#000000>042:</font> <strong><font color=#0000ff>private</font></strong><font color=#990000>:</font><br> <font color=#000000>043:</font> <strong><font color=#000080>    #ifdef</font></strong> _MT<br> <font color=#000000>044:</font>     <font color=#009900>long</font><br> <font color=#000000>045:</font> <strong><font color=#000080>    #else</font></strong><br> <font color=#000000>046:</font>     <font color=#009900>int</font><br> <font color=#000000>047:</font> <strong><font color=#000080>    #endif</font></strong><br> <font color=#000000>048:</font>     refCount_<font color=#990000>;</font><br> <font color=#000000>049:</font>     <strong><font color=#000000>RefCountable</font></strong><font color=#990000>(</font><strong><font color=#0000ff>const</font></strong> RefCountable <font color=#990000>&amp;</font><font color=#990000>)</font><font color=#990000>;</font><br> <font color=#000000>050:</font>     RefCountable <font color=#990000>&amp;</font> <strong><font color=#0000ff>operator</font></strong> <font color=#990000>=</font> <font color=#990000>(</font><strong><font color=#0000ff>const</font></strong> RefCountable <font color=#990000>&amp;</font><font color=#990000>)</font><font color=#990000>;</font><br> <font color=#000000>051:</font> <font color=#ff0000>}</font><font color=#990000>;</font><br> <font color=#000000>052:</font> <br> <font color=#000000>053:</font> <strong><font color=#0000ff>template</font></strong><font color=#990000>&lt;</font><strong><font color=#0000ff>class</font></strong> T<font color=#990000>&gt;</font><br> <font color=#000000>054:</font> <strong><font color=#0000ff>class</font></strong> RefCountedPtr <font color=#ff0000>{</font><br> <font color=#000000>055:</font> <strong><font color=#0000ff>public</font></strong><font color=#990000>:</font><br> <font color=#000000>056:</font>     <strong><font color=#000000>RefCountedPtr</font></strong><font color=#990000>(</font><font color=#009900>void</font><font color=#990000>)</font> <font color=#990000>:</font> <strong><font color=#000000>ptr_</font></strong><font color=#990000>(</font><font color=#993399>0</font><font color=#990000>)</font> <font color=#ff0000>{</font><font color=#ff0000>}</font><br> <font color=#000000>057:</font>     <strong><font color=#000000>RefCountedPtr</font></strong><font color=#990000>(</font>T <font color=#990000>*</font>ptr<font color=#990000>)</font> <font color=#990000>:</font> <strong><font color=#000000>ptr_</font></strong><font color=#990000>(</font>ptr<font color=#990000>)</font> <font color=#ff0000>{</font><br> <font color=#000000>058:</font>         <strong><font color=#0000ff>if</font></strong> <font color=#990000>(</font>ptr_<font color=#990000>)</font><br> <font color=#000000>059:</font>             ptr_<font color=#990000>-</font><font color=#990000>&gt;</font><strong><font color=#000000>addRef</font></strong><font color=#990000>(</font><font color=#990000>)</font><font color=#990000>;</font><br> <font color=#000000>060:</font>     <font color=#ff0000>}</font><br> <font color=#000000>061:</font>     <strong><font color=#000000>RefCountedPtr</font></strong><font color=#990000>(</font><strong><font color=#0000ff>const</font></strong> RefCountedPtr<font color=#990000>&lt;</font>T<font color=#990000>&gt;</font> <font color=#990000>&amp;</font>sour<font color=#990000>)</font> <font color=#990000>:</font> <strong><font color=#000000>ptr_</font></strong><font color=#990000>(</font>sour<font color=#990000>.</font>ptr_<font color=#990000>)</font> <font color=#ff0000>{</font><br> <font color=#000000>062:</font>         <strong><font color=#0000ff>if</font></strong> <font color=#990000>(</font>ptr_<font color=#990000>)</font><br> <font color=#000000>063:</font>             ptr_<font color=#990000>-</font><font color=#990000>&gt;</font><strong><font color=#000000>addRef</font></strong><font color=#990000>(</font><font color=#990000>)</font><font color=#990000>;</font><br> <font color=#000000>064:</font>     <font color=#ff0000>}</font><br> <font color=#000000>065:</font>     RefCountedPtr <font color=#990000>&amp;</font> <strong><font color=#0000ff>operator</font></strong> <font color=#990000>=</font> <font color=#990000>(</font><strong><font color=#0000ff>const</font></strong> RefCountedPtr<font color=#990000>&lt;</font>T<font color=#990000>&gt;</font> <font color=#990000>&amp;</font>right<font color=#990000>)</font> <font color=#ff0000>{</font><br> <font color=#000000>066:</font>         <strong><font color=#0000ff>if</font></strong> <font color=#990000>(</font><strong><font color=#0000ff>this</font></strong><font color=#990000>!</font><font color=#990000>=</font><font color=#990000>&amp;</font>right<font color=#990000>)</font> <font color=#ff0000>{</font><br> <font color=#000000>067:</font>             <strong><font color=#0000ff>if</font></strong> <font color=#990000>(</font><font color=#993399>0</font><font color=#990000>!</font><font color=#990000>=</font>ptr_<font color=#990000>)</font><br> <font color=#000000>068:</font>                 ptr_<font color=#990000>-</font><font color=#990000>&gt;</font><strong><font color=#000000>decRef</font></strong><font color=#990000>(</font><font color=#990000>)</font><font color=#990000>;</font><br> <font color=#000000>069:</font>             ptr_ <font color=#990000>=</font> right<font color=#990000>.</font>ptr_<font color=#990000>;</font><br> <font color=#000000>070:</font>             <strong><font color=#0000ff>if</font></strong> <font color=#990000>(</font>ptr_<font color=#990000>)</font><br> <font color=#000000>071:</font>                 ptr_<font color=#990000>-</font><font color=#990000>&gt;</font><strong><font color=#000000>addRef</font></strong><font color=#990000>(</font><font color=#990000>)</font><font color=#990000>;</font><br> <font color=#000000>072:</font>         <font color=#ff0000>}</font><br> <font color=#000000>073:</font>         <strong><font color=#0000ff>return</font></strong> <font color=#990000>*</font><strong><font color=#0000ff>this</font></strong><font color=#990000>;</font><br> <font color=#000000>074:</font>     <font color=#ff0000>}</font><br> <font color=#000000>075:</font>     <font color=#990000>~</font><strong><font color=#000000>RefCountedPtr</font></strong><font color=#990000>(</font><font color=#009900>void</font><font color=#990000>)</font> <font color=#ff0000>{</font><br> <font color=#000000>076:</font>         <strong><font color=#0000ff>if</font></strong> <font color=#990000>(</font><font color=#993399>0</font><font color=#990000>!</font><font color=#990000>=</font>ptr_<font color=#990000>)</font><br> <font color=#000000>077:</font>             ptr_<font color=#990000>-</font><font color=#990000>&gt;</font><strong><font color=#000000>decRef</font></strong><font color=#990000>(</font><font color=#990000>)</font><font color=#990000>;</font><br> <font color=#000000>078:</font>     <font color=#ff0000>}</font><br> <font color=#000000>079:</font> <br> <font color=#000000>080:</font>     T <font color=#990000>&amp;</font> <strong><font color=#0000ff>operator</font></strong><font color=#990000>*</font><font color=#990000>(</font><font color=#990000>)</font> <strong><font color=#0000ff>const</font></strong> <font color=#ff0000>{</font> <strong><font color=#0000ff>return</font></strong> <font color=#990000>*</font>ptr_<font color=#990000>;</font> <font color=#ff0000>}</font><br> <font color=#000000>081:</font>     T <font color=#990000>*</font> <strong><font color=#0000ff>operator</font></strong><font color=#990000>-</font><font color=#990000>&gt;</font><font color=#990000>(</font><font color=#990000>)</font> <strong><font color=#0000ff>const</font></strong> <font color=#ff0000>{</font> <strong><font color=#0000ff>return</font></strong> <font color=#990000>(</font><font color=#990000>&amp;</font><font color=#990000>*</font><font color=#990000>*</font><strong><font color=#0000ff>this</font></strong><font color=#990000>)</font><font color=#990000>;</font> <font color=#ff0000>}</font><br> <font color=#000000>082:</font>     <br> <font color=#000000>083:</font>     <strong><font color=#0000ff>friend</font></strong> <font color=#009900>bool</font> <strong><font color=#0000ff>operator</font></strong> <font color=#990000>=</font><font color=#990000>=</font> <font color=#990000>(</font><strong><font color=#0000ff>const</font></strong> RefCountedPtr<font color=#990000>&lt;</font>T<font color=#990000>&gt;</font> <font color=#990000>&amp;</font>left<font color=#990000>,</font> <strong><font color=#0000ff>const</font></strong> RefCountedPtr<font color=#990000>&lt;</font>T<font color=#990000>&gt;</font> <font color=#990000>&amp;</font>right<font color=#990000>)</font> <font color=#ff0000>{</font><br> <font color=#000000>084:</font>         <strong><font color=#0000ff>return</font></strong> <font color=#990000>(</font>left<font color=#990000>.</font>ptr_ <font color=#990000>=</font><font color=#990000>=</font> right<font color=#990000>.</font>ptr_<font color=#990000>)</font><font color=#990000>;</font><br> <font color=#000000>085:</font>     <font color=#ff0000>}</font><br> <font color=#000000>086:</font>     <strong><font color=#0000ff>friend</font></strong> <font color=#009900>bool</font> <strong><font color=#0000ff>operator</font></strong> <font color=#990000>!</font><font color=#990000>=</font> <font color=#990000>(</font><strong><font color=#0000ff>const</font></strong> RefCountedPtr<font color=#990000>&lt;</font>T<font color=#990000>&gt;</font> <font color=#990000>&amp;</font>left<font color=#990000>,</font> <strong><font color=#0000ff>const</font></strong> RefCountedPtr<font color=#990000>&lt;</font>T<font color=#990000>&gt;</font> <font color=#990000>&amp;</font>right<font color=#990000>)</font> <font color=#ff0000>{</font><br> <font color=#000000>087:</font>         <strong><font color=#0000ff>return</font></strong> <font color=#990000>(</font>left<font color=#990000>.</font>ptr_ <font color=#990000>!</font><font color=#990000>=</font> right<font color=#990000>.</font>ptr_<font color=#990000>)</font><font color=#990000>;</font><br> <font color=#000000>088:</font>     <font color=#ff0000>}</font><br> <font color=#000000>089:</font>     <strong><font color=#0000ff>friend</font></strong> <font color=#009900>bool</font> <strong><font color=#0000ff>operator</font></strong> <font color=#990000>&lt;</font> <font color=#990000>(</font><strong><font color=#0000ff>const</font></strong> RefCountedPtr<font color=#990000>&lt;</font>T<font color=#990000>&gt;</font> <font color=#990000>&amp;</font>left<font color=#990000>,</font> <strong><font color=#0000ff>const</font></strong> RefCountedPtr<font color=#990000>&lt;</font>T<font color=#990000>&gt;</font> <font color=#990000>&amp;</font>right<font color=#990000>)</font> <font color=#ff0000>{</font><br> <font color=#000000>090:</font>         <strong><font color=#0000ff>return</font></strong> <font color=#990000>(</font>left<font color=#990000>.</font>ptr_ <font color=#990000>&lt;</font> right<font color=#990000>.</font>ptr_<font color=#990000>)</font><font color=#990000>;</font><br> <font color=#000000>091:</font>     <font color=#ff0000>}</font><br> <font color=#000000>092:</font>     <strong><font color=#0000ff>friend</font></strong> <font color=#009900>bool</font> <strong><font color=#0000ff>operator</font></strong> <font color=#990000>&gt;</font> <font color=#990000>(</font><strong><font color=#0000ff>const</font></strong> RefCountedPtr<font color=#990000>&lt;</font>T<font color=#990000>&gt;</font> <font color=#990000>&amp;</font>left<font color=#990000>,</font> <strong><font color=#0000ff>const</font></strong> RefCountedPtr<font color=#990000>&lt;</font>T<font color=#990000>&gt;</font> <font color=#990000>&amp;</font>right<font color=#990000>)</font> <font color=#ff0000>{</font><br> <font color=#000000>093:</font>         <strong><font color=#0000ff>return</font></strong> <font color=#990000>(</font>left<font color=#990000>.</font>ptr_ <font color=#990000>&gt;</font> right<font color=#990000>.</font>ptr_<font color=#990000>)</font><font color=#990000>;</font><br> <font color=#000000>094:</font>     <font color=#ff0000>}</font><br> <font color=#000000>095:</font>     <strong><font color=#0000ff>friend</font></strong> <font color=#009900>bool</font> <strong><font color=#0000ff>operator</font></strong> <font color=#990000>&lt;</font><font color=#990000>=</font> <font color=#990000>(</font><strong><font color=#0000ff>const</font></strong> RefCountedPtr<font color=#990000>&lt;</font>T<font color=#990000>&gt;</font> <font color=#990000>&amp;</font>left<font color=#990000>,</font> <strong><font color=#0000ff>const</font></strong> RefCountedPtr<font color=#990000>&lt;</font>T<font color=#990000>&gt;</font> <font color=#990000>&amp;</font>right<font color=#990000>)</font> <font color=#ff0000>{</font><br> <font color=#000000>096:</font>         <strong><font color=#0000ff>return</font></strong> <font color=#990000>(</font>left<font color=#990000>.</font>ptr_ <font color=#990000>&lt;</font><font color=#990000>=</font> right<font color=#990000>.</font>ptr_<font color=#990000>)</font><font color=#990000>;</font><br> <font color=#000000>097:</font>     <font color=#ff0000>}</font><br> <font color=#000000>098:</font>     <strong><font color=#0000ff>friend</font></strong> <font color=#009900>bool</font> <strong><font color=#0000ff>operator</font></strong> <font color=#990000>&gt;</font><font color=#990000>=</font> <font color=#990000>(</font><strong><font color=#0000ff>const</font></strong> RefCountedPtr<font color=#990000>&lt;</font>T<font color=#990000>&gt;</font> <font color=#990000>&amp;</font>left<font color=#990000>,</font> <strong><font color=#0000ff>const</font></strong> RefCountedPtr<font color=#990000>&lt;</font>T<font color=#990000>&gt;</font> <font color=#990000>&amp;</font>right<font color=#990000>)</font> <font color=#ff0000>{</font><br> <font color=#000000>099:</font>         <strong><font color=#0000ff>return</font></strong> <font color=#990000>(</font>left<font color=#990000>.</font>ptr_ <font color=#990000>&gt;</font><font color=#990000>=</font> right<font color=#990000>.</font>ptr_<font color=#990000>)</font><font color=#990000>;</font><br> <font color=#000000>100:</font>     <font color=#ff0000>}</font><br> <font color=#000000>101:</font> <br> <font color=#000000>102:</font>     <font color=#009900>bool</font> <strong><font color=#000000>isNull</font></strong><font color=#990000>(</font><font color=#990000>)</font> <strong><font color=#0000ff>const</font></strong> <font color=#ff0000>{</font> <strong><font color=#0000ff>return</font></strong> <font color=#993399>0</font><font color=#990000>=</font><font color=#990000>=</font>ptr_<font color=#990000>;</font> <font color=#ff0000>}</font><br> <font color=#000000>103:</font>     <font color=#009900>bool</font> <strong><font color=#000000>isValid</font></strong><font color=#990000>(</font><font color=#990000>)</font> <strong><font color=#0000ff>const</font></strong> <font color=#ff0000>{</font> <strong><font color=#0000ff>return</font></strong> <font color=#993399>0</font><font color=#990000>!</font><font color=#990000>=</font>ptr_<font color=#990000>;</font> <font color=#ff0000>}</font><br> <font color=#000000>104:</font> <br> <font color=#000000>105:</font>     <em><font color=#9a1900>//</font></em><em><font color=#9a1900> 返回所控制的对象指针</font></em><br> <font color=#000000>106:</font>     T <font color=#990000>*</font> <strong><font color=#000000>get</font></strong><font color=#990000>(</font><font color=#009900>void</font><font color=#990000>)</font> <strong><font color=#0000ff>const</font></strong> <font color=#ff0000>{</font> <strong><font color=#0000ff>return</font></strong> ptr_<font color=#990000>;</font> <font color=#ff0000>}</font><br> <font color=#000000>107:</font> <br> <font color=#000000>108:</font>     <em><font color=#9a1900>//</font></em><em><font color=#9a1900>取得对另一指针的控制权</font></em><br> <font color=#000000>109:</font>     <font color=#009900>void</font> <strong><font color=#000000>reset</font></strong><font color=#990000>(</font>T <font color=#990000>*</font> ptr<font color=#990000>=</font><font color=#993399>0</font><font color=#990000>)</font> <font color=#ff0000>{</font><br> <font color=#000000>110:</font>         <strong><font color=#0000ff>if</font></strong> <font color=#990000>(</font><font color=#993399>0</font><font color=#990000>!</font><font color=#990000>=</font>ptr<font color=#990000>)</font><br> <font color=#000000>111:</font>             ptr<font color=#990000>-</font><font color=#990000>&gt;</font><strong><font color=#000000>addRef</font></strong><font color=#990000>(</font><font color=#990000>)</font><font color=#990000>;</font><br> <font color=#000000>112:</font>         <strong><font color=#0000ff>if</font></strong> <font color=#990000>(</font><font color=#993399>0</font><font color=#990000>!</font><font color=#990000>=</font>ptr_<font color=#990000>)</font><br> <font color=#000000>113:</font>             ptr_<font color=#990000>-</font><font color=#990000>&gt;</font><strong><font color=#000000>decRef</font></strong><font color=#990000>(</font><font color=#990000>)</font><font color=#990000>;</font><br> <font color=#000000>114:</font>         ptr_ <font color=#990000>=</font> ptr<font color=#990000>;</font><br> <font color=#000000>115:</font>     <font color=#ff0000>}</font><br> <font color=#000000>116:</font> <br> <font color=#000000>117:</font> <strong><font color=#0000ff>private</font></strong><font color=#990000>:</font><br> <font color=#000000>118:</font>     T    <font color=#990000>*</font>ptr_<font color=#990000>;</font><br> <font color=#000000>119:</font> <font color=#ff0000>}</font><font color=#990000>;</font><br> <font color=#000000>120:</font> <br> <font color=#000000>121:</font> <strong><font color=#000080>#endif</font></strong> <em><font color=#9a1900>//</font></em><em><font color=#9a1900> ifndef _REFCOUNTED_INCLUDED_</font></em></pre>
<img src ="http://www.cppblog.com/iniwf/aggbug/77036.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/iniwf/" target="_blank">iniwf</a> 2009-03-18 17:11 <a href="http://www.cppblog.com/iniwf/archive/2009/03/18/77036.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>高手戏玩c++</title><link>http://www.cppblog.com/iniwf/archive/2009/03/17/76896.html</link><dc:creator>iniwf</dc:creator><author>iniwf</author><pubDate>Tue, 17 Mar 2009 11:12:00 GMT</pubDate><guid>http://www.cppblog.com/iniwf/archive/2009/03/17/76896.html</guid><wfw:comment>http://www.cppblog.com/iniwf/comments/76896.html</wfw:comment><comments>http://www.cppblog.com/iniwf/archive/2009/03/17/76896.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/iniwf/comments/commentRss/76896.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/iniwf/services/trackbacks/76896.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 转自http://blog.csdn.net/chenhu_doc/archive/2006/08/10/1046370.aspx                        toupper,tolower地球人都知道 C++ 的 string 没有 toupper ，好在这不是个大问题，因为我们有 STL 算法：string s("heLLo");transform(s.beg...&nbsp;&nbsp;<a href='http://www.cppblog.com/iniwf/archive/2009/03/17/76896.html'>阅读全文</a><img src ="http://www.cppblog.com/iniwf/aggbug/76896.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/iniwf/" target="_blank">iniwf</a> 2009-03-17 19:12 <a href="http://www.cppblog.com/iniwf/archive/2009/03/17/76896.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>高质量C++/C编程指南</title><link>http://www.cppblog.com/iniwf/archive/2009/03/16/76801.html</link><dc:creator>iniwf</dc:creator><author>iniwf</author><pubDate>Mon, 16 Mar 2009 15:37:00 GMT</pubDate><guid>http://www.cppblog.com/iniwf/archive/2009/03/16/76801.html</guid><wfw:comment>http://www.cppblog.com/iniwf/comments/76801.html</wfw:comment><comments>http://www.cppblog.com/iniwf/archive/2009/03/16/76801.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/iniwf/comments/commentRss/76801.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/iniwf/services/trackbacks/76801.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: http://man.chinaunix.net/develop/c&amp;c++/c/c.htmhttp://cms.hit.edu.cn/file.php/21/%E9%AB%98%E8%B4%A8%E9%87%8FC_C%E7%BC%96%E7%A8%8B%E6%8C%87%E5%8D%97.pdf&lt;&lt; Back to man.ChinaUnix.net &nbsp;...&nbsp;&nbsp;<a href='http://www.cppblog.com/iniwf/archive/2009/03/16/76801.html'>阅读全文</a><img src ="http://www.cppblog.com/iniwf/aggbug/76801.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/iniwf/" target="_blank">iniwf</a> 2009-03-16 23:37 <a href="http://www.cppblog.com/iniwf/archive/2009/03/16/76801.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>The Complete Guide to C++ Strings, Part II - String Wrapper Classes</title><link>http://www.cppblog.com/iniwf/archive/2009/03/16/76797.html</link><dc:creator>iniwf</dc:creator><author>iniwf</author><pubDate>Mon, 16 Mar 2009 15:27:00 GMT</pubDate><guid>http://www.cppblog.com/iniwf/archive/2009/03/16/76797.html</guid><wfw:comment>http://www.cppblog.com/iniwf/comments/76797.html</wfw:comment><comments>http://www.cppblog.com/iniwf/archive/2009/03/16/76797.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/iniwf/comments/commentRss/76797.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/iniwf/services/trackbacks/76797.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 转自http://www.codeproject.com/KB/string/cppstringguide2.aspxIntroductionSince C-style strings can be error-prone and difficult to manage, not to mention a target for hackers looking for buffer over...&nbsp;&nbsp;<a href='http://www.cppblog.com/iniwf/archive/2009/03/16/76797.html'>阅读全文</a><img src ="http://www.cppblog.com/iniwf/aggbug/76797.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/iniwf/" target="_blank">iniwf</a> 2009-03-16 23:27 <a href="http://www.cppblog.com/iniwf/archive/2009/03/16/76797.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>The Complete Guide to C++ Strings, Part I - Win32 Character Encodings</title><link>http://www.cppblog.com/iniwf/archive/2009/03/16/76796.html</link><dc:creator>iniwf</dc:creator><author>iniwf</author><pubDate>Mon, 16 Mar 2009 15:26:00 GMT</pubDate><guid>http://www.cppblog.com/iniwf/archive/2009/03/16/76796.html</guid><wfw:comment>http://www.cppblog.com/iniwf/comments/76796.html</wfw:comment><comments>http://www.cppblog.com/iniwf/archive/2009/03/16/76796.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/iniwf/comments/commentRss/76796.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/iniwf/services/trackbacks/76796.html</trackback:ping><description><![CDATA[转自<a href="http://www.codeproject.com/KB/string/cppstringguide1.aspx">http://www.codeproject.com/KB/string/cppstringguide1.aspx</a><br><br>
<h2>Introduction</h2>
<p>You've undoubtedly seen all these various string types like <code>TCHAR</code>, <code>std::<span class=code-SDKkeyword>string</span></code>, <code>BSTR</code>, and so on. And then there are those wacky macros starting with <code>_tcs</code>. And you're staring at the screen thinking "wha?" Well stare no more, this guide will outline the purpose of each string type, show some simple usages, and describe how to convert to other string types when necessary.</p>
<p>In Part I, I will cover the three types of character encodings. It is <em>crucial</em> that you understand how the encoding schemes work. Even if you already know that a string is an array of characters, read this part. Once you've learned this, it will be clearer how the various string classes are related.</p>
<p>In Part II I will describe the string classes themselves, when to use which ones, and how to convert among them.</p>
<h2>The basics of characters - ASCII, DBCS, Unicode</h2>
<p>All string classes eventually boil down to a C-style string, and C-style strings are arrays of characters, so I'll first cover the character types. There are three encoding schemes and three character types. The first scheme is the <strong>single-byte character set</strong>, or <strong>SBCS</strong>. In this encoding scheme, all characters are exactly one byte long. ASCII is an example of an SBCS. A single zero byte marks the end of a SBCS string.</p>
<p>The second scheme is the <strong>multi-byte character set</strong>, or <strong>MBCS</strong>. An MBCS encoding contains some characters that are one byte long, and others that are more than one byte long. The MBCS schemes used in Windows contain two character types, <strong>single-byte characters</strong> and <strong>double-byte characters</strong>. Since the largest multi-byte character used in Windows is two bytes long, the term <strong>double-byte character set</strong>, or <strong>DBCS</strong>, is commonly used in place of MBCS.</p>
<p>In a DBCS encoding, certain values are reserved to indicate that they are part of a double-byte character. For example, in the Shift-JIS encoding (a commonly-used Japanese scheme), values 0x81-0x9F and 0xE0-0xFC mean "this is a double-byte character, and the next byte is part of this character." Such values are called "lead bytes," and are <em>always</em> greater than 0x7F. The byte following a lead byte is called the "trail byte." In DBCS, the trail byte can be any non-zero value. Just as in SBCS, the end of a DBCS string is marked by a single zero byte.</p>
<p>The third scheme is <strong>Unicode</strong>. Unicode is an encoding standard in which all characters are two bytes long. <strong>Unicode characters</strong> are sometimes called <strong>wide characters</strong> because they are wider (use more storage) than single-byte characters. Note that Unicode is not considered an MBCS - the distinguishing feature of an MBCS encoding is that characters are of different lengths. A Unicode string is terminated by two zero bytes (the encoding of the value 0 in a wide character).</p>
<p>Single-byte characters are the Latin alphabet, accented characters, and graphics defined in the ASCII standard and DOS operating system. Double-byte characters are used in East Asian and Middle Eastern languages. Unicode is used in COM and internally in Windows NT.</p>
<p>You're certainly already familiar with single-byte characters. When you use the <code><span class=code-keyword>char</span></code> data type, you are dealing with single-byte characters. Double-byte characters are also manipulated using the <code><span class=code-keyword>char</span></code> data type (which is the first of many oddities that we'll encounter with double-byte characters). Unicode characters are represented by the <code><span class=code-keyword>wchar_t</span></code> type. Unicode character and string literals are written by prefixing the literal with <code>L</code>, for example:</p>
<div class=SmallText id=premain0 style="WIDTH: 100%"><img id=preimg0 style="CURSOR: pointer" height=9 src="http://www.codeproject.com/images/minus.gif" width=9 preid="0"><span id=precollapse0 style="MARGIN-BOTTOM: 0px; CURSOR: pointer" preid="0"> Collapse</span><img style="MARGIN-LEFT: 35px" height=16 src="http://www.codeproject.com/images/copy_16.png" width=16><a href="http://www.codeproject.com/KB/string/cppstringguide1.aspx#" preid="0"><u><font color=#800080> Copy Code</font></u></a></div>
<pre id=pre0 style="MARGIN-TOP: 0px">  <span class=code-keyword>wchar_t</span>  wch = L<span class=code-string>'</span><span class=code-string>1'</span>;      <span class=code-comment>//</span><span class=code-comment> 2 bytes, 0x0031
</span>  <span class=code-keyword>wchar_t</span>* wsz = L<span class=code-string>"</span><span class=code-string>Hello"</span>;  <span class=code-comment>//</span><span class=code-comment> 12 bytes, 6 wide characters</span></pre>
<h2>How characters are stored in memory</h2>
<p>Single-byte strings are stored one character after the next, with a single zero byte marking the end of the string. So for example, <code><span class=code-string>"</span><span class=code-string>Bob"</span></code> is stored as:</p>
<p>
<table cellSpacing=0 cellPadding=0 border=0>
    <tbody>
        <tr>
            <td>
            <p><code><span class=code-digit>42</span> </code></p>
            </td>
            <td>
            <p><code>6F </code></p>
            </td>
            <td>
            <p><code><span class=code-digit>62</span> </code></p>
            </td>
            <td>
            <p><code><span class=code-digit>00</span> </code></p>
            </td>
        </tr>
        <tr>
            <td>
            <p align=center><code>B</code> </p>
            </td>
            <td>
            <p align=center><code>o</code> </p>
            </td>
            <td>
            <p align=center><code>b</code> </p>
            </td>
            <td>
            <p><code>EOS</code> </p>
            </td>
        </tr>
    </tbody>
</table>
</p>
<p>The Unicode version, <code>L<span class=code-string>"</span><span class=code-string>Bob"</span></code>, is stored as:</p>
<p>
<table cellSpacing=0 cellPadding=0 border=0>
    <tbody>
        <tr>
            <td>
            <p><code><span class=code-digit>42</span> <span class=code-digit>00</span> </code></p>
            </td>
            <td>
            <p><code>6F <span class=code-digit>00</span> </code></p>
            </td>
            <td>
            <p><code><span class=code-digit>62</span> <span class=code-digit>00</span> </code></p>
            </td>
            <td>
            <p><code><span class=code-digit>00</span> <span class=code-digit>00</span> </code></p>
            </td>
        </tr>
        <tr>
            <td>
            <p align=center><code>B</code> </p>
            </td>
            <td>
            <p align=center><code>o</code> </p>
            </td>
            <td>
            <p align=center><code>b</code> </p>
            </td>
            <td>
            <p align=center><code>EOS</code> </p>
            </td>
        </tr>
    </tbody>
</table>
</p>
<p>with the character 0x0000 (the Unicode encoding of zero) marking the end.</p>
<p>DBCS strings look like SBCS strings at first glance, but we will see later that there are subtleties that make a difference when using string manipulating functions and traversing through the string with a pointer. The string "<img height=13 src="http://www.codeproject.com/KB/string/CPPStringGuide1/nihongo.gif" width=36 align=middle border=0>" ("nihongo") is stored as follows (with lead bytes and trail bytes indicated by LB and TB respectively):</p>
<p>
<table cellSpacing=0 cellPadding=0 border=0>
    <tbody>
        <tr>
            <td>
            <p><code><span class=code-digit>93</span> FA </code></p>
            </td>
            <td>
            <p><code><span class=code-digit>96</span> 7B </code></p>
            </td>
            <td>
            <p><code>8C EA </code></p>
            </td>
            <td>
            <p><code><span class=code-digit>00</span> </code></p>
            </td>
        </tr>
        <tr>
            <td>
            <p><code>LB TB </code></p>
            </td>
            <td>
            <p><code>LB TB</code> </p>
            </td>
            <td>
            <p><code>LB TB</code> </p>
            </td>
            <td>
            <p><code>EOS</code> </p>
            </td>
        </tr>
        <tr>
            <td>
            <p align=center><img height=13 src="http://www.codeproject.com/KB/string/CPPStringGuide1/ni.gif" width=10 align=bottom border=0> </p>
            </td>
            <td>
            <p align=center><img height=13 src="http://www.codeproject.com/KB/string/CPPStringGuide1/hon.gif" width=13 align=bottom border=0> </p>
            </td>
            <td>
            <p align=center><img height=13 src="http://www.codeproject.com/KB/string/CPPStringGuide1/go.gif" width=13 align=bottom border=0> </p>
            </td>
            <td>
            <p><code>EOS</code> </p>
            </td>
        </tr>
    </tbody>
</table>
</p>
<p>Keep in mind that the value of "ni" is not interpreted as the <code>WORD</code> value 0xFA93. The two values <code><span class=code-digit>93</span></code> and <code>FA</code>, <em>in that order</em>, together encode the character "ni". (So on a big-endian CPU, the bytes would still be in the order shown above.)</p>
<h2>Using string handling functions</h2>
<p>We've all seen the C string functions like <code>strcpy()</code>, <code>sprintf()</code>, <code>atol()</code>, etc. These functions must be used <em>only</em> with single-byte strings. The standard library also has versions for use with <em>only</em> Unicode strings, such as <code>wcscpy()</code>, <code>swprintf()</code>, <code>_wtol()</code>.</p>
<p>Microsoft also added versions to their CRT (C runtime library) that operate on DBCS strings. The <code>strxxx()</code> functions have corresponding DBCS versions named <code>_mbsxxx()</code>. If you ever expect to encounter DBCS strings (and you will if your software is ever installed on Japanese, Chinese, or other language that uses DBCS), you should <em>always</em> use the <code>_mbsxxx()</code> functions, since they also accept SBCS strings. (A DBCS string might contain only one-byte characters, so that's why <code>_mbsxxx()</code> functions work with SBCS strings too.)</p>
<p>Let's look at a typical string to illustrate the need for the different versions of the string handling functions. Going back to our Unicode string <code>L<span class=code-string>"</span><span class=code-string>Bob"</span></code>:</p>
<p>
<table cellSpacing=0 cellPadding=0 border=0>
    <tbody>
        <tr>
            <td>
            <p><code><span class=code-digit>42</span> <span class=code-digit>00</span> </code></p>
            </td>
            <td>
            <p><code>6F <span class=code-digit>00</span> </code></p>
            </td>
            <td>
            <p><code><span class=code-digit>62</span> <span class=code-digit>00</span> </code></p>
            </td>
            <td>
            <p><code><span class=code-digit>00</span> <span class=code-digit>00</span> </code></p>
            </td>
        </tr>
        <tr>
            <td>
            <p align=center><code>B</code> </p>
            </td>
            <td>
            <p align=center><code>o</code> </p>
            </td>
            <td>
            <p align=center><code>b</code> </p>
            </td>
            <td>
            <p align=center><code>EOS</code> </p>
            </td>
        </tr>
    </tbody>
</table>
</p>
<p>Because x86 CPUs are little-endian, the value 0x0042 is stored in memory as <code><span class=code-digit>42</span> <span class=code-digit>00</span></code>. Can you see the problem here if this string were passed to <code>strlen()</code>? It would see the first byte <code><span class=code-digit>42</span></code>, then <code><span class=code-digit>00</span></code>, which to it means "end of the string," and it would return 1. The converse situation, passing <code><span class=code-string>"</span><span class=code-string>Bob"</span></code> to <code>wcslen()</code>, is even worse. <code>wcslen()</code> would first see 0x6F42, then 0x0062, and then keep on reading past the end of your buffer until it happened to hit a <code><span class=code-digit>00</span> <span class=code-digit>00</span></code> sequence or cause a GPF.</p>
<p>So we've covered the usage of <code>strxxx()</code> versus <code>wcsxxx()</code>. What about <code>strxxx()</code> versus <code>_mbsxxx()</code>? The difference there is <em>extremely</em> important, and has to do with the proper way of traversing through DBCS strings. I will cover traversing strings next, then return to the subject of <code>strxxx()</code> versus <code>_mbsxxx()</code>.</p>
<h2>Traversing and indexing into strings properly</h2>
<p>Since most of us grew up using SBCS strings, we're used to using the <code>++</code> and <code>--</code> operators on a pointer to traverse through a string. We've also used array notation to access any character in the string. Both these methods work perfectly well with SBCS and Unicode strings, because all characters are the same length and the compiler can properly return the character we're asking for.</p>
<p>However, you <strong>must</strong> break those habits for your code to work properly when it encounters DBCS strings. There are two rules for traversing through a DBCS string using a pointer. Breaking these rules will cause almost all of your DBCS-related bugs.</p>
<blockquote>
<p>1. Don't traverse forwards with <code>++</code> unless you check for lead bytes along the way.</p>
<p>2. <strong>Never</strong> traverse backwards using <code>--</code>.</p>
</blockquote>
<p>I'll illustrate rule 2 first, since it's easy to find a non-contrived example of code that breaks it. Say you have a program that stores a config file in its own directory, and you keep the install directory in the registry. At runtime, you read the install directory, tack on the config filename, and try to read it. So if you install to <code>C:\Program Files\MyCoolApp</code>, the filename that gets constructed is <code>C:\Program Files\MyCoolApp\config.bin</code>, and it works perfectly when you test it.</p>
<p>Now, imagine this is your code that constructs the filename:</p>
<div class=SmallText id=premain1 style="WIDTH: 100%"><img id=preimg1 style="CURSOR: pointer" height=9 src="http://www.codeproject.com/images/minus.gif" width=9 preid="1"><span id=precollapse1 style="MARGIN-BOTTOM: 0px; CURSOR: pointer" preid="1"> Collapse</span><img style="MARGIN-LEFT: 35px" height=16 src="http://www.codeproject.com/images/copy_16.png" width=16><a href="http://www.codeproject.com/KB/string/cppstringguide1.aspx#" preid="1"><u><font color=#800080> Copy Code</font></u></a></div>
<pre id=pre1 style="MARGIN-TOP: 0px"><span class=code-keyword>bool</span> GetConfigFileName ( <span class=code-keyword>char</span>* pszName, size_t nBuffSize )
{
<span class=code-keyword>char</span> szConfigFilename[MAX_PATH];
<span class=code-comment>//</span><span class=code-comment> Read install dir from registry... we'll assume it succeeds.
</span>
<span class=code-comment>//</span><span class=code-comment> Add on a backslash if it wasn't present in the registry value.
</span>    <span class=code-comment>//</span><span class=code-comment> First, get a pointer to the terminating zero.
</span><span class=code-keyword>char</span>* pLastChar = strchr ( szConfigFilename, <span class=code-string>'</span><span class=code-string>\0'</span> );
<span class=code-comment>//</span><span class=code-comment> Now move it back one character.
</span>    pLastChar--;
<span class=code-keyword>if</span> ( *pLastChar != <span class=code-string>'</span><span class=code-string>\\'</span> )
strcat ( szConfigFilename, <span class=code-string>"</span><span class=code-string>\\" );
// Add on the name of the config file.
strcat ( szConfigFilename, "</span>config.bin<span class=code-string>"</span><span class=code-string> );
// If the caller's buffer is big enough, return the filename.
if ( strlen ( szConfigFilename ) &gt;= nBuffSize )
return false;
else
{
strcpy ( pszName, szConfigFilename );
return true;
}
}</span></pre>
<p>This is very defensive code, yet it will break with particular DBCS characters. To see why, suppose a Japanese user gets hold of your program and changes the install directory to <code>C:\</code><img height=13 src="http://www.codeproject.com/KB/string/CPPStringGuide1/youkoso.gif" width=35 align=bottom border=0>. Here is that directory name as stored in memory:</p>
<p>
<table cellSpacing=0 cellPadding=0 border=0>
    <tbody>
        <tr>
            <td>
            <p><code><span class=code-digit>43</span></code> </p>
            </td>
            <td>
            <p><code>3A</code> </p>
            </td>
            <td>
            <p><code>5C</code> </p>
            </td>
            <td>
            <p><code><span class=code-digit>83</span> <span class=code-digit>88</span></code> </p>
            </td>
            <td>
            <p><code><span class=code-digit>83</span> <span class=code-digit>45</span></code> </p>
            </td>
            <td>
            <p><code><span class=code-digit>83</span> <span class=code-digit>52</span></code> </p>
            </td>
            <td>
            <p><code><span class=code-digit>83</span> 5C</code> </p>
            </td>
            <td>
            <p><code><span class=code-digit>00</span></code> </p>
            </td>
        </tr>
        <tr>
            <td>
            <p>&nbsp; </p>
            </td>
            <td>
            <p>&nbsp; </p>
            </td>
            <td>
            <p>&nbsp; </p>
            </td>
            <td>
            <p><code>LB TB</code> </p>
            </td>
            <td>
            <p><code>LB TB</code> </p>
            </td>
            <td>
            <p><code>LB TB</code> </p>
            </td>
            <td>
            <p><code>LB TB</code> </p>
            </td>
            <td>
            <p>&nbsp; </p>
            </td>
        </tr>
        <tr>
            <td>
            <p><code>C</code> </p>
            </td>
            <td>
            <p><code>:</code> </p>
            </td>
            <td>
            <p><code>\</code> </p>
            </td>
            <td>
            <p align=center><img height=11 src="http://www.codeproject.com/KB/string/CPPStringGuide1/yo.gif" width=9 align=bottom border=0> </p>
            </td>
            <td>
            <p align=center><img height=13 src="http://www.codeproject.com/KB/string/CPPStringGuide1/u.gif" width=10 align=bottom border=0> </p>
            </td>
            <td>
            <p align=center><img height=11 src="http://www.codeproject.com/KB/string/CPPStringGuide1/ko.gif" width=9 align=bottom border=0> </p>
            </td>
            <td>
            <p align=center><img height=12 src="http://www.codeproject.com/KB/string/CPPStringGuide1/so.gif" width=10 align=bottom border=0> </p>
            </td>
            <td>
            <p><code>EOS</code> </p>
            </td>
        </tr>
    </tbody>
</table>
</p>
<p>When <code>GetConfigFileName()</code> checks for the trailing backslash, it looks at the last non-zero byte of the install directory, sees that it equals <code><span class=code-string>'</span><span class=code-string>\\'</span></code>, and doesn't append another slash. The result is that the code returns the wrong filename.</p>
<p>So what went wrong? Look at the two bytes above highlighted in blue. The value of the backslash character is 0x5C. The value of <code><span class=code-string>'</span><span class=code-string></span></code><img height=12 src="http://www.codeproject.com/KB/string/CPPStringGuide1/so.gif" width=10 align=bottom border=0><code><span class=code-string>'</span><span class=code-string></span></code> is <code><span class=code-digit>83</span></code> <code>5C</code>. (The light bulb should be going on just about now...) The above code mistakenly read a trail byte and treated it as a character of its own.</p>
<p>The correct way to traverse backwards is to use functions that are aware of DBCS characters and move the pointer the correct number of bytes. Here is the correct code, with the pointer movement shown in red:</p>
<div class=SmallText id=premain2 style="WIDTH: 100%"><img id=preimg2 style="CURSOR: pointer" height=9 src="http://www.codeproject.com/images/minus.gif" width=9 preid="2"><span id=precollapse2 style="MARGIN-BOTTOM: 0px; CURSOR: pointer" preid="2"> Collapse</span><img style="MARGIN-LEFT: 35px" height=16 src="http://www.codeproject.com/images/copy_16.png" width=16><a href="http://www.codeproject.com/KB/string/cppstringguide1.aspx#" preid="2"><u><font color=#800080> Copy Code</font></u></a></div>
<pre id=pre2 style="MARGIN-TOP: 0px"><span class=code-keyword>bool</span> FixedGetConfigFileName ( <span class=code-keyword>char</span>* pszName, size_t nBuffSize )
{
<span class=code-keyword>char</span> szConfigFilename[MAX_PATH];
<span class=code-comment>//</span><span class=code-comment> Read install dir from registry... we'll assume it succeeds.
</span>
<span class=code-comment>//</span><span class=code-comment> Add on a backslash if it wasn't present in the registry value.
</span>    <span class=code-comment>//</span><span class=code-comment> First, get a pointer to the terminating zero.
</span><span class=code-keyword>char</span>* pLastChar = _mbschr ( szConfigFilename, <span class=code-string>'</span><span class=code-string>\0'</span> );
<span class=code-comment>//</span><span class=code-comment> Now move it back one double-byte character.
</span>    pLastChar = CharPrev ( szConfigFilename, pLastChar );
<span class=code-keyword>if</span> ( *pLastChar != <span class=code-string>'</span><span class=code-string>\\'</span> )
_mbscat ( szConfigFilename, <span class=code-string>"</span><span class=code-string>\\" );
// Add on the name of the config file.
_mbscat ( szConfigFilename, "</span>config.bin<span class=code-string>"</span><span class=code-string> );
// If the caller's buffer is big enough, return the filename.
if ( _mbslen ( szInstallDir ) &gt;= nBuffSize )
return false;
else
{
_mbscpy ( pszName, szConfigFilename );
return true;
}
}</span></pre>
<p>This fixed function uses the <code>CharPrev()</code> API to move <code>pLastChar</code> back one character, which might be two bytes long if the string ends in a double-byte character. In this version, the if condition works properly, since a lead byte will never equal 0x5C.</p>
<p>You can probably imagine a way to break rule 1 now. For example, you might validate a filename entered by the user by looking for multiple occurrences of the character <code><span class=code-string>'</span><span class=code-string>:'</span></code>. If you use <code>++</code> to traverse the string instead of <code>CharNext()</code>, you may incorrectly generate errors if there happen to be trail bytes whose values equal that of <code><span class=code-string>'</span><span class=code-string>:'</span></code>.</p>
<p>Related to rule 2 is this one about using array indexes:</p>
<blockquote>
<p>2a. <strong>Never</strong> calculate an index into a string using subtraction.</p>
</blockquote>
<p>Code that breaks this rule is very similar to code that breaks rule 2. For example, if <code>pLastChar</code> were set this way:</p>
<div class=SmallText id=premain3 style="WIDTH: 100%"><img id=preimg3 style="CURSOR: pointer" height=9 src="http://www.codeproject.com/images/minus.gif" width=9 preid="3"><span id=precollapse3 style="MARGIN-BOTTOM: 0px; CURSOR: pointer" preid="3"> Collapse</span><img style="MARGIN-LEFT: 35px" height=16 src="http://www.codeproject.com/images/copy_16.png" width=16><a href="http://www.codeproject.com/KB/string/cppstringguide1.aspx#" preid="3"><u><font color=#800080> Copy Code</font></u></a></div>
<pre id=pre3 style="MARGIN-TOP: 0px"><span class=code-keyword>char</span>* pLastChar = &amp;szConfigFilename [strlen(szConfigFilename) - <span class=code-digit>1</span>];</pre>
<p>it would break in exactly the same situations, because subtracting 1 in the index expression is equivalent to moving backwards 1 byte, which breaks rule 2.</p>
<h2>Back to strxxx() versus _mbsxxx()</h2>
<p>It should be clear now why the <code>_mbsxxx()</code> functions are necessary. The <code>strxxx()</code> functions know nothing of DBCS characters, while <code>_mbsxxx()</code> do. If you called <code>strrchr(<span class=code-string>"</span><span class=code-string>C:\\</span></code><img height=13 src="http://www.codeproject.com/KB/string/CPPStringGuide1/youkoso.gif" width=35 align=bottom border=0><code><span class=code-string>"</span><span class=code-string>, '\\')</span></code> the return value would be wrong, whereas <code>_mbsrchr()</code> will recognize the double-byte characters at the end, and return a pointer to the last actual backslash.</p>
<p>One final point about string functions: the <code>strxxx()</code> and <code>_mbsxxx()</code> functions that take or return a length return the length in <code><span class=code-keyword>char</span></code>s. So if a string contains three double-byte characters, <code>_mbslen()</code> will return 6. The Unicode functions return lengths in <code><span class=code-keyword>wchar_t</span></code>s, so for example, <code>wcslen(L<span class=code-string>"</span><span class=code-string>Bob"</span>)</code> returns 3.</p>
<h2>MBCS and Unicode in the Win32 API</h2>
<h3>The two sets of APIs</h3>
<p>Although you might never have noticed, every API and message in Win32 that deals with strings has two versions. One version accepts MCBS strings, and the other Unicode strings. For example, there is no API called <code>SetWindowText()</code>; instead, there are <code>SetWindowTextA()</code> and <code>SetWindowTextW()</code>. The A suffix (for ANSI) indicates the MBCS function, while the W suffix (for wide) indicates the Unicode version.</p>
<p>When you build a Windows program, you can elect to use either the MBCS or Unicode APIs. If you've used the VC AppWizards and never touched the preprocessor settings, you've been using the MBCS versions all along. So how is it that we can write "SetWindowText" when there isn't an API by that name? The winuser.h header file contains some <code><span class=code-preprocessor>#define</span></code>s, like this:</p>
<div class=SmallText id=premain4 style="WIDTH: 100%"><img id=preimg4 style="CURSOR: pointer" height=9 src="http://www.codeproject.com/images/minus.gif" width=9 preid="4"><span id=precollapse4 style="MARGIN-BOTTOM: 0px; CURSOR: pointer" preid="4"> Collapse</span><img style="MARGIN-LEFT: 35px" height=16 src="http://www.codeproject.com/images/copy_16.png" width=16><a href="http://www.codeproject.com/KB/string/cppstringguide1.aspx#" preid="4"><u><font color=#800080> Copy Code</font></u></a></div>
<pre id=pre4 style="MARGIN-TOP: 0px">BOOL WINAPI SetWindowTextA ( HWND hWnd, LPCSTR lpString );
BOOL WINAPI SetWindowTextW ( HWND hWnd, LPCWSTR lpString );
#ifdef UNICODE
<span class=code-preprocessor>#define</span> SetWindowText  SetWindowTextW
<span class=code-preprocessor>#else</span>
<span class=code-preprocessor>#define</span> SetWindowText  SetWindowTextA
<span class=code-preprocessor>#endif</span></pre>
<p>When building for the MBCS APIs, <code>UNICODE</code> is not defined, so the preprocessor sees:</p>
<div class=SmallText id=premain5 style="WIDTH: 100%"><img id=preimg5 style="CURSOR: pointer" height=9 src="http://www.codeproject.com/images/minus.gif" width=9 preid="5"><span id=precollapse5 style="MARGIN-BOTTOM: 0px; CURSOR: pointer" preid="5"> Collapse</span><img style="MARGIN-LEFT: 35px" height=16 src="http://www.codeproject.com/images/copy_16.png" width=16><a href="http://www.codeproject.com/KB/string/cppstringguide1.aspx#" preid="5"><u><font color=#800080> Copy Code</font></u></a></div>
<pre id=pre5 style="MARGIN-TOP: 0px"><span class=code-preprocessor>#define</span> SetWindowText  SetWindowTextA</pre>
<p>and replaces calls to <code>SetWindowText()</code> with calls to the real API, <code>SetWindowTextA()</code>. (Note that you can, if you wanted to, call <code>SetWindowTextA()</code> or <code>SetWindowTextW()</code> directly, although you'd rarely need to do that.)</p>
<p>So, if you want to switch to using the Unicode APIs by default, you can go to the preprocessor settings and remove the <code>_MBCS</code> symbol from the list of predefined symbols, and add <code>UNICODE</code> and <code>_UNICODE</code>. (You should define both, as different headers use different symbols.) However, you will run into a snag if you've been using plain <code><span class=code-keyword>char</span></code> for your strings. Consider this code:</p>
<div class=SmallText id=premain6 style="WIDTH: 100%"><img id=preimg6 style="CURSOR: pointer" height=9 src="http://www.codeproject.com/images/minus.gif" width=9 preid="6"><span id=precollapse6 style="MARGIN-BOTTOM: 0px; CURSOR: pointer" preid="6"> Collapse</span><img style="MARGIN-LEFT: 35px" height=16 src="http://www.codeproject.com/images/copy_16.png" width=16><a href="http://www.codeproject.com/KB/string/cppstringguide1.aspx#" preid="6"><u><font color=#800080> Copy Code</font></u></a></div>
<pre id=pre6 style="MARGIN-TOP: 0px">HWND hwnd = GetSomeWindowHandle();
<span class=code-keyword>char</span> szNewText[] = <span class=code-string>"</span><span class=code-string>we love Bob!"</span>;
SetWindowText ( hwnd, szNewText );</pre>
<p>After the compiler replaces "SetWindowText" with "SetWindowTextW", the code becomes:</p>
<div class=SmallText id=premain7 style="WIDTH: 100%"><img id=preimg7 style="CURSOR: pointer" height=9 src="http://www.codeproject.com/images/minus.gif" width=9 preid="7"><span id=precollapse7 style="MARGIN-BOTTOM: 0px; CURSOR: pointer" preid="7"> Collapse</span><img style="MARGIN-LEFT: 35px" height=16 src="http://www.codeproject.com/images/copy_16.png" width=16><a href="http://www.codeproject.com/KB/string/cppstringguide1.aspx#" preid="7"><u><font color=#800080> Copy Code</font></u></a></div>
<pre id=pre7 style="MARGIN-TOP: 0px">HWND hwnd = GetSomeWindowHandle();
<span class=code-keyword>char</span> szNewText[] = <span class=code-string>"</span><span class=code-string>we love Bob!"</span>;
SetWindowTextW ( hwnd, szNewText );</pre>
<p>See the problem here? We're passing a single-byte string to a function that takes a Unicode string. The first solution to this problem is to use <code>#ifdef</code>s around the definition of the string variable:</p>
<div class=SmallText id=premain8 style="WIDTH: 100%"><img id=preimg8 style="CURSOR: pointer" height=9 src="http://www.codeproject.com/images/minus.gif" width=9 preid="8"><span id=precollapse8 style="MARGIN-BOTTOM: 0px; CURSOR: pointer" preid="8"> Collapse</span><img style="MARGIN-LEFT: 35px" height=16 src="http://www.codeproject.com/images/copy_16.png" width=16><a href="http://www.codeproject.com/KB/string/cppstringguide1.aspx#" preid="8"><u><font color=#800080> Copy Code</font></u></a></div>
<pre id=pre8 style="MARGIN-TOP: 0px">HWND hwnd = GetSomeWindowHandle();
#ifdef UNICODE
<span class=code-keyword>wchar_t</span> szNewText[] = L<span class=code-string>"</span><span class=code-string>we love Bob!"</span>;
<span class=code-preprocessor>#else</span>
<span class=code-keyword>char</span> szNewText[] = <span class=code-string>"</span><span class=code-string>we love Bob!"</span>;
<span class=code-preprocessor>#endif</span>
SetWindowText ( hwnd, szNewText );</pre>
<p>You can probably imagine the headache you'd get having to do that around every string in your code. The solution to this is the <code>TCHAR</code>.</p>
<h3>TCHAR to the rescue!</h3>
<p><code>TCHAR</code> is a character type that lets you use the same codebase for both MBCS and Unicode builds, without putting messy <code><span class=code-preprocessor>#define</span></code>s all over your code. A definition of the <code>TCHAR</code> looks like this:</p>
<div class=SmallText id=premain9 style="WIDTH: 100%"><img id=preimg9 style="CURSOR: pointer" height=9 src="http://www.codeproject.com/images/minus.gif" width=9 preid="9"><span id=precollapse9 style="MARGIN-BOTTOM: 0px; CURSOR: pointer" preid="9"> Collapse</span><img style="MARGIN-LEFT: 35px" height=16 src="http://www.codeproject.com/images/copy_16.png" width=16><a href="http://www.codeproject.com/KB/string/cppstringguide1.aspx#" preid="9"><u><font color=#800080> Copy Code</font></u></a></div>
<pre id=pre9 style="MARGIN-TOP: 0px">#ifdef UNICODE
<span class=code-keyword>typedef</span> <span class=code-keyword>wchar_t</span> TCHAR;
<span class=code-preprocessor>#else</span>
<span class=code-keyword>typedef</span> <span class=code-keyword>char</span> TCHAR;
<span class=code-preprocessor>#endif</span></pre>
<p>So a <code>TCHAR</code> is a <code><span class=code-keyword>char</span></code> in MBCS builds, and a <code><span class=code-keyword>wchar_t</span></code> in Unicode builds. There is also a macro <code>_T()</code> to deal with the <code>L</code> prefix needed for Unicode string literals:</p>
<div class=SmallText id=premain10 style="WIDTH: 100%"><img id=preimg10 style="CURSOR: pointer" height=9 src="http://www.codeproject.com/images/minus.gif" width=9 preid="10"><span id=precollapse10 style="MARGIN-BOTTOM: 0px; CURSOR: pointer" preid="10"> Collapse</span><img style="MARGIN-LEFT: 35px" height=16 src="http://www.codeproject.com/images/copy_16.png" width=16><a href="http://www.codeproject.com/KB/string/cppstringguide1.aspx#" preid="10"><u><font color=#800080> Copy Code</font></u></a></div>
<pre id=pre10 style="MARGIN-TOP: 0px">#ifdef UNICODE
<span class=code-preprocessor>#define</span> _T(x) L##x
<span class=code-preprocessor>#else</span>
<span class=code-preprocessor>#define</span> _T(x) x
<span class=code-preprocessor>#endif</span></pre>
<p>The <code>##</code> is a preprocessor operator that pastes the two arguments together. Whenever you have a string literal in your code, use the <code>_T</code> macro on it, and it will have the <code>L</code> prefix added on when you do a Unicode build.</p>
<div class=SmallText id=premain11 style="WIDTH: 100%"><img id=preimg11 style="CURSOR: pointer" height=9 src="http://www.codeproject.com/images/minus.gif" width=9 preid="11"><span id=precollapse11 style="MARGIN-BOTTOM: 0px; CURSOR: pointer" preid="11"> Collapse</span><img style="MARGIN-LEFT: 35px" height=16 src="http://www.codeproject.com/images/copy_16.png" width=16><a href="http://www.codeproject.com/KB/string/cppstringguide1.aspx#" preid="11"><u><font color=#800080> Copy Code</font></u></a></div>
<pre id=pre11 style="MARGIN-TOP: 0px">TCHAR szNewText[] = _T(<span class=code-string>"</span><span class=code-string>we love Bob!"</span>);</pre>
<p>Just as there are macros to hide the <code>SetWindowTextA</code>/<code>W</code> details, there are also macros that you can use in place of the <code>strxxx()</code> and <code>_mbsxxx()</code> string functions. For example, you can use the <code>_tcsrchr</code> macro in place of <code>strrchr()</code> or <code>_mbsrchr()</code> or <code>wcsrchr()</code>. <code>_tcsrchr</code> expands to the right function based on whether you have the <code>_MBCS</code> or <code>UNICODE</code> symbol defined, just like <code>SetWindowText</code> does.</p>
<p>It's not just the <code>strxxx()</code> functions that have <code>TCHAR</code> macros. There are also, for example, <code>_stprintf</code> (replaces <code>sprintf()</code> and <code>swprintf()</code>) and <code>_tfopen</code> (replaces <code>fopen()</code> and <code>_wfopen()</code>). The full list of macros is in MSDN under the title "Generic-Text Routine Mappings."</p>
<h3>String and TCHAR typedefs</h3>
<p>Since the Win32 API documentation lists functions by their common names (for example, "SetWindowText"), all strings are given in terms of <code>TCHAR</code>s. (The exception to this is Unicode-only APIs introduced in XP.) Here are the commonly-used typedefs that you will see in MSDN:</p>
<p>
<table cellPadding=0 border=1>
    <tbody>
        <tr>
            <th>
            <p>type </p>
            </th>
            <th>
            <p>Meaning in MBCS builds </p>
            </th>
            <th>
            <p>Meaning in Unicode builds </p>
            </th>
        </tr>
        <tr>
            <td>
            <p><code>WCHAR</code> </p>
            </td>
            <td>
            <p><code><span class=code-keyword>wchar_t</span></code> </p>
            </td>
            <td>
            <p><code><span class=code-keyword>wchar_t</span></code> </p>
            </td>
        </tr>
        <tr>
            <td>
            <p><code>LPSTR</code> </p>
            </td>
            <td>
            <p>zero-terminated string of <code><span class=code-keyword>char</span></code> (<code><span class=code-keyword>char</span>*</code>) </p>
            </td>
            <td>
            <p>zero-terminated string of <code><span class=code-keyword>char</span></code> (<code><span class=code-keyword>char</span>*</code>) </p>
            </td>
        </tr>
        <tr>
            <td>
            <p><code>LPCSTR</code> </p>
            </td>
            <td>
            <p>constant zero-terminated string of <code><span class=code-keyword>char</span></code> (<code><span class=code-keyword>const</span> <span class=code-keyword>char</span>*</code>) </p>
            </td>
            <td>
            <p>constant zero-terminated string of <code><span class=code-keyword>char</span></code> (<code><span class=code-keyword>const</span> <span class=code-keyword>char</span>*</code>) </p>
            </td>
        </tr>
        <tr>
            <td>
            <p><code>LPWSTR</code> </p>
            </td>
            <td>
            <p>zero-terminated Unicode string (<code><span class=code-keyword>wchar_t</span>*</code>) </p>
            </td>
            <td>
            <p>zero-terminated Unicode string (<code><span class=code-keyword>wchar_t</span>*</code>) </p>
            </td>
        </tr>
        <tr>
            <td>
            <p><code>LPCWSTR</code> </p>
            </td>
            <td>
            <p>constant zero-terminated Unicode string (<code><span class=code-keyword>const</span> <span class=code-keyword>wchar_t</span>*</code>) </p>
            </td>
            <td>
            <p>constant zero-terminated Unicode string (<code><span class=code-keyword>const</span> <span class=code-keyword>wchar_t</span>*</code>) </p>
            </td>
        </tr>
        <tr>
            <td>
            <p><code>TCHAR</code> </p>
            </td>
            <td>
            <p><code><span class=code-keyword>char</span></code> </p>
            </td>
            <td>
            <p><code><span class=code-keyword>wchar_t</span></code> </p>
            </td>
        </tr>
        <tr>
            <td>
            <p><code>LPTSTR</code> </p>
            </td>
            <td>
            <p>zero-terminated string of <code>TCHAR</code> (<code>TCHAR*</code>) </p>
            </td>
            <td>
            <p>zero-terminated string of <code>TCHAR</code> (<code>TCHAR*</code>) </p>
            </td>
        </tr>
        <tr>
            <td>
            <p><code>LPCTSTR</code> </p>
            </td>
            <td>
            <p>constant zero-terminated string of <code>TCHAR</code> (<code><span class=code-keyword>const</span> TCHAR*</code>) </p>
            </td>
            <td>
            <p>constant zero-terminated string of <code>TCHAR</code> (<code><span class=code-keyword>const</span> TCHAR*</code>) </p>
            </td>
        </tr>
    </tbody>
</table>
</p>
<h2>When to use TCHAR and Unicode</h2>
<p>So, after all this, you're probably wondering, "So why would I use Unicode? I've gotten by with plain <code><span class=code-keyword>char</span></code>s for years." There are three cases where a Unicode build is beneficial:</p>
<ol>
    <li>Your program will run <em>only</em> on Windows NT.
    <li>Your program needs to handle filenames longer than <code>MAX_PATH</code> characters.
    <li>Your program uses some newer APIs introduced with Windows XP that do not have the separate A/W versions. </li>
</ol>
<p>The vast majority of Unicode APIs are not implemented on Windows 9x, so if you intend your program to be run on 9x, you'll have to stick with the MBCS APIs. (There is a relatively new library from Microsoft called the Microsoft Layer for Unicode that lets you use Unicode on 9x, however I have not tried it myself yet, so I can't comment on how well it works.) However, since NT uses Unicode for everything internally, you will speed up your program by using the Unicode APIs. Every time you pass a string to an MBCS API, the operating system converts the string to Unicode and calls the corresponding Unicode API. If a string is returned, the OS has to convert the string back. While this conversion process is (hopefully) highly optimized to make as little impact as possible, it is still a speed penalty that is avoidable.</p>
<p>NT allows very long filenames (longer than the normal limit of <code>MAX_PATH</code> characters, which is 260) but only if you use the Unicode APIs. Once nice side benefit of using the Unicode APIs is that your program will automatically handle any language that the user enters. So a user could enter a filename using English, Chinese, and Japanese all together, and you wouldn't need any special code to deal with it; they all appear as Unicode characters to you.</p>
<p>Finally, with the end of the Windows 9x line, MS seems to be doing away with the MBCS APIs. For example, the <code>SetWindowTheme()</code> API, which takes two string parameters, only has a Unicode version. Using a Unicode build will simplify string handling as you won't have to convert from MBCS to Unicode and back.</p>
<p>And even if you don't go with Unicode builds now, you should definitely <em>always</em>&nbsp;use <code>TCHAR</code> and the associated macros. Not only will that go a long way to making your code DBCS-safe, but if you decide to make a Unicode build in the future, you'll just need to change a preprocessor setting to do it! <!-- Article Ends --><!-- Main Page Contents End --></p>
<form id=aspnetForm style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px" name=aspnetForm action=cppstringguide1.aspx method=post>
    <div><input id=__VIEWSTATE type=hidden value=/wEPDwULLTEwMDUyNjYzMjgPZBYCZg9kFgQCCw9kFgYCAw8PFgIeB1Zpc2libGVnZGQCCQ8PFgIfAGdkZAIMDw8WAh8AZ2RkAgwPZBYKAgcPZBYOAgEPZBYCZg8WAh4LXyFJdGVtQ291bnRmZAIDD2QWCmYPDxYCHgtOYXZpZ2F0ZVVybAUtL0tCL3N0cmluZy9jcHBzdHJpbmdndWlkZTEuYXNweD9kaXNwbGF5PVByaW50ZGQCAQ8PFgIfAgUlL3NjcmlwdC9BcnRpY2xlcy9SZXBvcnQuYXNweD9haWQ9Mjk5NWRkAgIPDxYCHwBoZGQCAw8PFgIfAGhkZAIFDw8WAh8CBTAvc2NyaXB0L2NvbW1vbi9UZWxsRnJpZW5kLmFzcHg/b2J0aWQ9MiZvYmlkPTI5OTVkZAIFD2QWBAIBD2QWAgIBDw8WAh4EVGV4dAUbMTk2IHZvdGVzIGZvciB0aGlzIEFydGljbGUuZGQCBg9kFgJmD2QWBAIBDw8WBB8DBRFQb3B1bGFyaXR5OiAxMS4xMx8CBSkvc2NyaXB0L0FydGljbGVzL1RvcEFydGljbGVzLmFzcHg/dGFfc289MWRkAgUPFgIfAwUcUmF0aW5nOiA8Yj40Ljg2PC9iPiBvdXQgb2YgNWQCGQ9kFgoCAQ9kFgQCAQ8WAh4JaW5uZXJodG1sBbECPHA+VGhpcyBhcnRpY2xlIGhhcyBubyBleHBsaWNpdCBsaWNlbnNlIGF0dGFjaGVkIHRvIGl0IGJ1dCBtYXkgY29udGFpbiB1c2FnZSB0ZXJtcyBpbiB0aGUgYXJ0aWNsZSB0ZXh0IG9yIHRoZSBkb3dubG9hZCBmaWxlcyB0aGVtc2VsdmVzLiBJZiBpbiBkb3VidCBwbGVhc2UgY29udGFjdCB0aGUgYXV0aG9yIHZpYSB0aGUgZGlzY3Vzc2lvbiBib2FyZCBiZWxvdy48L3A+PHA+QSBsaXN0IG9mIGxpY2Vuc2VzIGF1dGhvcnMgbWlnaHQgdXNlIGNhbiBiZSBmb3VuZCA8YSBocmVmPSIvaW5mby9MaWNlbnNlcy5hc3B4Ij5oZXJlPC9hPjwvcD5kAgIPZBYCAgEPEGRkFgBkAgUPFgIfAQIBZAIHDxYCHwMFygg8aDI+T3RoZXIgcG9wdWxhciBTdHJpbmcgaGFuZGxpbmcgYXJ0aWNsZXM6PC9oMj48dWw+PGxpPjxhIGhyZWY9Ii9LQi9zdHJpbmcvY3Bwc3RyaW5nZ3VpZGUxLmFzcHgiPlRoZSBDb21wbGV0ZSBHdWlkZSB0byBDKysgU3RyaW5ncywgUGFydCBJIC0gV2luMzIgQ2hhcmFjdGVyIEVuY29kaW5nczwvYT48ZGl2IGNsYXNzPSJTbWFsbFRleHQiPkEgZ3VpZGUgdG8gdGhlIG11bHRpdHVkZSBvZiBzdHJpbmcgdHlwZXMgdXNlZCBpbiBXaW5kb3dzLjwvZGl2PjwvbGk+PGxpPjxhIGhyZWY9Ii9LQi9zdHJpbmcvY3Bwc3RyaW5nZ3VpZGUyLmFzcHgiPlRoZSBDb21wbGV0ZSBHdWlkZSB0byBDKysgU3RyaW5ncywgUGFydCBJSSAtIFN0cmluZyBXcmFwcGVyIENsYXNzZXM8L2E+PGRpdiBjbGFzcz0iU21hbGxUZXh0Ij5BIGd1aWRlIHRvIHRoZSBzdHJpbmcgd3JhcHBlciBjbGFzc2VzIHByb3ZpZGVkIGJ5IFZpc3VhbCBDKysgYW5kIGNsYXNzIGxpYnJhcmllczwvZGl2PjwvbGk+PGxpPjxhIGhyZWY9Ii9LQi9zdHJpbmcvY3N0cmluZ21nbXQuYXNweCI+Q1N0cmluZyBNYW5hZ2VtZW50PC9hPjxkaXYgY2xhc3M9IlNtYWxsVGV4dCI+TGVhcm4gaG93IHRvIGVmZmVjdGl2ZWx5IHVzZSBDU3RyaW5ncy48L2Rpdj48L2xpPjxsaT48YSBocmVmPSIvS0Ivc3RyaW5nL3N0ZHN0cmluZy5hc3B4Ij5DU3RyaW5nLWNsb25lIFVzaW5nIFN0YW5kYXJkIEMrKzwvYT48ZGl2IGNsYXNzPSJTbWFsbFRleHQiPkEgRHJvcC1JbiByZXBsYWNlbWVudCBmb3IgQ1N0cmluZyB0aGF0IGJ1aWxkcyBvbiB0aGUgU3RhbmRhcmQgQysrIExpYnJhcnkncyBiYXNpY19zdHJpbmcgdGVtcGxhdGU8L2Rpdj48L2xpPjxsaT48YSBocmVmPSIvS0Ivc3RyaW5nL3dpbGRjbXAuYXNweCI+V2lsZGNhcmQgc3RyaW5nIGNvbXBhcmUgKGdsb2JiaW5nKTwvYT48ZGl2IGNsYXNzPSJTbWFsbFRleHQiPk1hdGNoZXMgYSBzdHJpbmcgYWdhaW5zdCBhIHdpbGRjYXJkIHN0cmluZyBzdWNoIGFzICZxdW90OyouKiZxdW90OyBvciAmcXVvdDtibD9oLiomcXVvdDsgZXRjLiBUaGlzIGlzIGdvb2QgZm9yIGZpbGUgZ2xvYmJpbmcgb3IgdG8gbWF0Y2ggaG9zdG1hc2tzLjwvZGl2PjwvbGk+PC91bD5kAgkPDxYCHwBnZGQCDQ9kFgJmD2QWAgIBD2QWAmYPZBYCAgkPFgIfAGgWAgIBDxBkZBYAZAIbDw8WAh8AZ2RkAh0PDxYCHwBnZGQCJQ8WAh8AaGQCCQ8PFgIfAgUmL3NjcmlwdC9BcnRpY2xlcy9BcnRpY2xlLmFzcHg/YWlkPTI5OTVkZAIPDxYCHwMFCjQgT2N0IDIwMDJkAhEPDxYEHwMFDE1pY2hhZWwgRHVubh8CBSgvc2NyaXB0L01lbWJlcnNoaXAvUHJvZmlsZXMuYXNweD9taWQ9MTUyZGQCEw8WAh8DBR5Db3B5cmlnaHQgMjAwMiBieSBNaWNoYWVsIER1bm5kZKvHriVoDEPqcGzUnXBkFWxKVP5/ name=__VIEWSTATE> </div>
    <h2>License</h2>
    <div id=ctl00_LicenseTerms>
    <p>This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.</p>
    <p>A list of licenses authors might use can be found <a href="http://www.codeproject.com/info/Licenses.aspx"><u><font color=#0000ff>here</font></u></a></p>
    </div>
    <h2>About the Author</h2>
    <table cellSpacing=5 cellPadding=0 width="100%" border=0>
        <tbody>
            <tr vAlign=top>
                <td id=ctl00_AboutAuthorRptr_ctl00_AboutAuthor_memberPhotoTable style="WIDTH: 155px" vAlign=top><strong><a id=ctl00_AboutAuthorRptr_ctl00_AboutAuthor_memberProfileLink href="http://www.codeproject.com/script/Membership/Profiles.aspx?mid=152"><u><font color=#0000ff>Michael Dunn</font></u></a></strong><br></td>
            </tr>
        </tbody>
    </table>
</form>
<img src ="http://www.cppblog.com/iniwf/aggbug/76796.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/iniwf/" target="_blank">iniwf</a> 2009-03-16 23:26 <a href="http://www.cppblog.com/iniwf/archive/2009/03/16/76796.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>编写一个STL 中的CString类</title><link>http://www.cppblog.com/iniwf/archive/2009/03/16/76795.html</link><dc:creator>iniwf</dc:creator><author>iniwf</author><pubDate>Mon, 16 Mar 2009 15:20:00 GMT</pubDate><guid>http://www.cppblog.com/iniwf/archive/2009/03/16/76795.html</guid><wfw:comment>http://www.cppblog.com/iniwf/comments/76795.html</wfw:comment><comments>http://www.cppblog.com/iniwf/archive/2009/03/16/76795.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/iniwf/comments/commentRss/76795.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/iniwf/services/trackbacks/76795.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: STL英文是Standard Template Library，也就是我们常说的C 标准模板库,。该标准库于1998年被正式纳入C 标准，给全世界的C 程序员带来了福音。最让我们兴奋的应该是它的跨平台性，使得你在WINDOW，UNIX ,Linux等操作系统上面用标准C 编写的程序不用修改即可移植。(当然要有C 的编译器)。 现在的编译器虽然对标准C 支持程度不同，单总体上还是很好。Windows...&nbsp;&nbsp;<a href='http://www.cppblog.com/iniwf/archive/2009/03/16/76795.html'>阅读全文</a><img src ="http://www.cppblog.com/iniwf/aggbug/76795.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/iniwf/" target="_blank">iniwf</a> 2009-03-16 23:20 <a href="http://www.cppblog.com/iniwf/archive/2009/03/16/76795.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Implementing a simple smart pointer in c++</title><link>http://www.cppblog.com/iniwf/archive/2009/03/16/76786.html</link><dc:creator>iniwf</dc:creator><author>iniwf</author><pubDate>Mon, 16 Mar 2009 14:15:00 GMT</pubDate><guid>http://www.cppblog.com/iniwf/archive/2009/03/16/76786.html</guid><wfw:comment>http://www.cppblog.com/iniwf/comments/76786.html</wfw:comment><comments>http://www.cppblog.com/iniwf/archive/2009/03/16/76786.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/iniwf/comments/commentRss/76786.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/iniwf/services/trackbacks/76786.html</trackback:ping><description><![CDATA[<h2>Introduction</h2>
<p>What are smart pointers? The answer is fairly simple; a smart pointer is a pointer which is smart. What does that mean? Actually smart pointers are objects which behave like pointers, but do more than a pointer. These objects are flexible as pointers and have the advantage of being an object (like constructor and destructors called automatically). A smart pointer is designed to handle the problems caused by using normal pointers (hence called smart).
<h2>Problems with Pointers</h2>
<p>What are the common problems we face in C++ programs while using pointers? The answer is memory management. Have a look at the following code. </p>
<div class=SmallText id=premain0 style="WIDTH: 100%"><img id=preimg0 style="CURSOR: pointer" height=9 src="http://www.codeproject.com/images/minus.gif" width=9 preid="0"><span id=precollapse0 style="MARGIN-BOTTOM: 0px; CURSOR: pointer" preid="0"> Collapse</span><img style="MARGIN-LEFT: 35px" height=16 src="http://www.codeproject.com/images/copy_16.png" width=16><a href="http://www.codeproject.com/KB/cpp/SmartPointers.aspx#" preid="0"><u><font color=#800080> Copy Code</font></u></a></div>
<pre id=pre0 style="MARGIN-TOP: 0px">    <span class=code-keyword>char</span>* pName  = <span class=code-keyword>new</span> <span class=code-keyword>char</span>[<span class=code-digit>1024</span>];
&#8230;
SetName(pName);
&#8230;
&#8230;
<span class=code-keyword>if</span>(null != pName)
{
<span class=code-keyword>delete</span>[] pName;
}
</pre>
<p>How many times we found out a bug which was caused because we forgot deleting <code>&#8216;pName&#8217;</code>. It would be great if somebody takes care of releasing the memory when the pointer is not useful (we are not talking about the garbage collector here). What if the pointer itself takes care of that, yes that&#8217;s exactly what smart pointer is intended to do. Let us write a smart pointer and see how we can handle a pointer better.
<p>We shall start with a realistic example. Let&#8217;s say we have a class called <code>Person</code> which is defined as listed below. </p>
<div class=SmallText id=premain1 style="WIDTH: 100%"><img id=preimg1 style="CURSOR: pointer" height=9 src="http://www.codeproject.com/images/minus.gif" width=9 preid="1"><span id=precollapse1 style="MARGIN-BOTTOM: 0px; CURSOR: pointer" preid="1"> Collapse</span><img style="MARGIN-LEFT: 35px" height=16 src="http://www.codeproject.com/images/copy_16.png" width=16><a href="http://www.codeproject.com/KB/cpp/SmartPointers.aspx#" preid="1"><u><font color=#800080> Copy Code</font></u></a></div>
<pre id=pre1 style="MARGIN-TOP: 0px">    <span class=code-keyword>class</span> Person
{
<span class=code-keyword>int</span> age;
<span class=code-keyword>char</span>* pName;
<span class=code-keyword>public</span>:
Person(): pName(<span class=code-digit>0</span>),age(<span class=code-digit>0</span>)
{
}
Person(<span class=code-keyword>char</span>* pName, <span class=code-keyword>int</span> age): pName(pName), age(age)
{
}
~Person()
{
}
<span class=code-keyword>void</span> Display()
{
printf(<span class=code-string>"</span><span class=code-string>Name = %s Age = %d \n"</span>, pName, age);
}
<span class=code-keyword>void</span> Shout()
{
printf(<span class=code-string>"</span><span class=code-string>Ooooooooooooooooo"</span>,);
}
};
</pre>
<p>Now we shall write the client code to use <code>Person</code> </p>
<div class=SmallText id=premain2 style="WIDTH: 100%"><img id=preimg2 style="CURSOR: pointer" height=9 src="http://www.codeproject.com/images/minus.gif" width=9 preid="2"><span id=precollapse2 style="MARGIN-BOTTOM: 0px; CURSOR: pointer" preid="2"> Collapse</span><img style="MARGIN-LEFT: 35px" height=16 src="http://www.codeproject.com/images/copy_16.png" width=16><a href="http://www.codeproject.com/KB/cpp/SmartPointers.aspx#" preid="2"><u><font color=#800080> Copy Code</font></u></a></div>
<pre id=pre2 style="MARGIN-TOP: 0px">    <span class=code-keyword>void</span> main()
{
Person* pPerson  = <span class=code-keyword>new</span> Person(<span class=code-string>"</span><span class=code-string>Scott"</span>, <span class=code-digit>25</span>);
pPerson-<span class=code-keyword>&gt;</span>Display();
<span class=code-keyword>delete</span> pPerson;
}
</pre>
<p>Now look at this code, every time I create a pointer I need to take care of deleting it, this is exactly what I want to avoid. I need some automatic mechanism which deletes the pointer. One thing which strikes to me is a destructor. But pointers do not have destructors, so what our smart pointer can have one. So we will create a class called <code>SP</code> which can hold a pointer to the <code>person</code> class and will delete the pointer when its destructor is called. Hence my client code will change to something like this. </p>
<div class=SmallText id=premain3 style="WIDTH: 100%"><img id=preimg3 style="CURSOR: pointer" height=9 src="http://www.codeproject.com/images/minus.gif" width=9 preid="3"><span id=precollapse3 style="MARGIN-BOTTOM: 0px; CURSOR: pointer" preid="3"> Collapse</span><img style="MARGIN-LEFT: 35px" height=16 src="http://www.codeproject.com/images/copy_16.png" width=16><a href="http://www.codeproject.com/KB/cpp/SmartPointers.aspx#" preid="3"><u><font color=#800080> Copy Code</font></u></a></div>
<pre id=pre3 style="MARGIN-TOP: 0px">    <span class=code-keyword>void</span> main()
{
SP p(<span class=code-keyword>new</span> Person(<span class=code-string>"</span><span class=code-string>Scott"</span>, <span class=code-digit>25</span>));
p-<span class=code-keyword>&gt;</span>Display();
<span class=code-comment>//</span><span class=code-comment> Dont need to delete Person pointer..
</span>    }
</pre>
Note the following things
<li>We have created an object of class <code>SP</code> which holds our <code>Person</code> class pointer. Since the destructor of <code>SP</code> class will be called when this object goes out of scope, it will delete the <code>Person</code> class pointer (as its main responsibility); hence we don&#8217;t have the pain of deleting the pointer.
<li>One more thing of major importance is that we should be able to call the <code>Display</code> method using the <code>SP </code>class object the way we used to call using the <code>Person</code> class pointer, i.e. the class should behave exactly like a pointer.
<h2>Interface for a smart pointer:</h2>
<p>Since the smart pointer should behave like a pointer, it should support the same interface as the pointers do; i.e. they should support the following operations. </p>
<li>Dereferencing (operator *)
<li>Indirection (operator -&gt;)
<p>Let us write the <code>SP</code> class now </p>
<div class=SmallText id=premain4 style="WIDTH: 100%"><img id=preimg4 style="CURSOR: pointer" height=9 src="http://www.codeproject.com/images/minus.gif" width=9 preid="4"><span id=precollapse4 style="MARGIN-BOTTOM: 0px; CURSOR: pointer" preid="4"> Collapse</span><img style="MARGIN-LEFT: 35px" height=16 src="http://www.codeproject.com/images/copy_16.png" width=16><a href="http://www.codeproject.com/KB/cpp/SmartPointers.aspx#" preid="4"><u><font color=#800080> Copy Code</font></u></a></div>
<pre id=pre4 style="MARGIN-TOP: 0px">    <span class=code-keyword>class</span> SP
{
<span class=code-keyword>private</span>:
Person*    pData; <span class=code-comment>//</span><span class=code-comment> pointer to person class
</span>    <span class=code-keyword>public</span>:
SP(Person* pValue) : pData(pValue)
{
}
~SP()
{
<span class=code-comment>//</span><span class=code-comment> pointer no longer requried
</span>            <span class=code-keyword>delete</span> pData;
}
Person&amp; <span class=code-keyword>operator</span>* ()
{
<span class=code-keyword>return</span> *pData;
}
Person* <span class=code-keyword>operator</span>-<span class=code-keyword>&gt;</span> ()
{
<span class=code-keyword>return</span> pData;
}
};
</pre>
This class is our smart pointer class. The main responsibility of this class is to hold a pointer to <code>Person</code> class, and then delete it when its destructor is called. It should also support the interface of the pointer.
<h2>Generic smart pointer class </h2>
One problem which we see here is that we can use this smart pointer class for pointer of <code>Person</code> class only. This means that we have to create each smart pointer class for each type, that&#8217;s not easy. We can solve this problem by making use of templates and make this smart pointer class generic. So let us change the code like this.
<div class=SmallText id=premain5 style="WIDTH: 100%"><img id=preimg5 style="CURSOR: pointer" height=9 src="http://www.codeproject.com/images/minus.gif" width=9 preid="5"><span id=precollapse5 style="MARGIN-BOTTOM: 0px; CURSOR: pointer" preid="5"> Collapse</span><img style="MARGIN-LEFT: 35px" height=16 src="http://www.codeproject.com/images/copy_16.png" width=16><a href="http://www.codeproject.com/KB/cpp/SmartPointers.aspx#" preid="5"><u><font color=#800080> Copy Code</font></u></a></div>
<pre id=pre5 style="MARGIN-TOP: 0px">    <span class=code-keyword>template</span> <span class=code-keyword>&lt;</span> <span class=code-keyword>typename</span> T <span class=code-keyword>&gt;</span> <span class=code-keyword>class</span> SP
{
<span class=code-keyword>private</span>:
T*    pData; <span class=code-comment>//</span><span class=code-comment> Generic pointer to be stored
</span>        <span class=code-keyword>public</span>:
SP(T* pValue) : pData(pValue)
{
}
~SP()
{
<span class=code-keyword>delete</span> pData;
}
T&amp; <span class=code-keyword>operator</span>* ()
{
<span class=code-keyword>return</span> *pData;
}
T* <span class=code-keyword>operator</span>-<span class=code-keyword>&gt;</span> ()
{
<span class=code-keyword>return</span> pData;
}
};
<span class=code-keyword>void</span> main()
{
SP
<person> p(<span class=code-keyword>new</span> Person(<span class=code-string>"</span><span class=code-string>Scott"</span>, <span class=code-digit>25</span>));
p-<span class=code-keyword>&gt;</span>Display();
<span class=code-comment>//</span><span class=code-comment> Dont need to delete Person pointer..
</span>    }
</pre>
<p>Now we can use our smart pointer class for any type of pointers. So is our smart pointer really smart? Check the following code segment. </p>
<div class=SmallText id=premain6 style="WIDTH: 100%"><img id=preimg6 style="CURSOR: pointer" height=9 src="http://www.codeproject.com/images/minus.gif" width=9 preid="6"><span id=precollapse6 style="MARGIN-BOTTOM: 0px; CURSOR: pointer" preid="6"> Collapse</span><img style="MARGIN-LEFT: 35px" height=16 src="http://www.codeproject.com/images/copy_16.png" width=16><a href="http://www.codeproject.com/KB/cpp/SmartPointers.aspx#" preid="6"><u><font color=#800080> Copy Code</font></u></a></div>
<pre id=pre6 style="MARGIN-TOP: 0px">    <span class=code-keyword>void</span> main()
{
SP
<person> p(<span class=code-keyword>new</span> Person(<span class=code-string>"</span><span class=code-string>Scott"</span>, <span class=code-digit>25</span>));
p-<span class=code-keyword>&gt;</span>Display();
{
SP
<person> q = p;
q-<span class=code-keyword>&gt;</span>Display();
<span class=code-comment>//</span><span class=code-comment> Destructor of Q will be called here..
</span>        }
p-<span class=code-keyword>&gt;</span>Display();
}
</pre>
Look what happens here <code>p</code> and <code>q</code> are referring to the same <code>Person</code> class pointer, now when <code>q</code> goes out of scope the destructor of <code>q</code> will be called which deletes the <code>Person</code> class pointer. Now we cannot call <code>p-<span class=code-keyword>&gt;</span>Display();</code> since <code>p</code> will be left with a dangling pointer and this call will fail. (Note that this problem would have existed even if we were using normal pointers instead of smart pointers) We should not delete the <code>Person</code> class pointer unless no body is using it. How do we do that? Implementing reference counting mechanism in our smart pointer class will solve this problem.
<h2>Reference counting</h2>
What we are going to do is we will have a reference counting class <code>RC</code>. This class will maintain an integer value which represents the reference count. We will have methods to increment and decrement the reference count.
<div class=SmallText id=premain7 style="WIDTH: 100%"><img id=preimg7 style="CURSOR: pointer" height=9 src="http://www.codeproject.com/images/minus.gif" width=9 preid="7"><span id=precollapse7 style="MARGIN-BOTTOM: 0px; CURSOR: pointer" preid="7"> Collapse</span><img style="MARGIN-LEFT: 35px" height=16 src="http://www.codeproject.com/images/copy_16.png" width=16><a href="http://www.codeproject.com/KB/cpp/SmartPointers.aspx#" preid="7"><u><font color=#800080> Copy Code</font></u></a></div>
<pre id=pre7 style="MARGIN-TOP: 0px">    <span class=code-keyword>class</span> RC
{
<span class=code-keyword>private</span>:
<span class=code-keyword>int</span> count; <span class=code-comment>//</span><span class=code-comment> Reference count
</span>
<span class=code-keyword>public</span>:
<span class=code-keyword>void</span> AddRef()
{
<span class=code-comment>//</span><span class=code-comment> Increment the reference count
</span>            count++;
}
<span class=code-keyword>int</span> Release()
{
<span class=code-comment>//</span><span class=code-comment> Decrement the reference count and
</span>            <span class=code-comment>//</span><span class=code-comment> return the reference count.
</span>            <span class=code-keyword>return</span> --count;
}
};
</pre>
<p>Now we have a reference counting class, we will introduce this to our smart pointer class. We will maintain a pointer to class <code>RC</code> in our <code>SP</code> class and this pointer will be shared for all instance of the smart pointer which refers to the same pointer. For this to happen we need to have an assignment operator and copy constructor in our <code>SP</code> class. </p>
<div class=SmallText id=premain8 style="WIDTH: 100%"><img id=preimg8 style="CURSOR: pointer" height=9 src="http://www.codeproject.com/images/minus.gif" width=9 preid="8"><span id=precollapse8 style="MARGIN-BOTTOM: 0px; CURSOR: pointer" preid="8"> Collapse</span><img style="MARGIN-LEFT: 35px" height=16 src="http://www.codeproject.com/images/copy_16.png" width=16><a href="http://www.codeproject.com/KB/cpp/SmartPointers.aspx#" preid="8"><u><font color=#800080> Copy Code</font></u></a></div>
<pre id=pre8 style="MARGIN-TOP: 0px">    <span class=code-keyword>template</span> <span class=code-keyword>&lt;</span> <span class=code-keyword>typename</span> T <span class=code-keyword>&gt;</span> <span class=code-keyword>class</span> SP
{
<span class=code-keyword>private</span>:
T*    pData;       <span class=code-comment>//</span><span class=code-comment> pointer
</span>        RC* reference; <span class=code-comment>//</span><span class=code-comment> Reference count
</span>
<span class=code-keyword>public</span>:
SP() : pData(<span class=code-digit>0</span>), reference(<span class=code-digit>0</span>)
{
<span class=code-comment>//</span><span class=code-comment> Create a new reference
</span>            reference = <span class=code-keyword>new</span> RC();
<span class=code-comment>//</span><span class=code-comment> Increment the reference count
</span>            reference-<span class=code-keyword>&gt;</span>AddRef();
}
SP(T* pValue) : pData(pValue), reference(<span class=code-digit>0</span>)
{
<span class=code-comment>//</span><span class=code-comment> Create a new reference
</span>            reference = <span class=code-keyword>new</span> RC();
<span class=code-comment>//</span><span class=code-comment> Increment the reference count
</span>            reference-<span class=code-keyword>&gt;</span>AddRef();
}
SP(<span class=code-keyword>const</span> SP<span class=code-keyword>&lt;</span>T<span class=code-keyword>&gt;</span>&amp; sp) : pData(sp.pData), reference(sp.reference)
{
<span class=code-comment>//</span><span class=code-comment> Copy constructor
</span>            <span class=code-comment>//</span><span class=code-comment> Copy the data and reference pointer
</span>            <span class=code-comment>//</span><span class=code-comment> and increment the reference count
</span>            reference-<span class=code-keyword>&gt;</span>AddRef();
}
~SP()
{
<span class=code-comment>//</span><span class=code-comment> Destructor
</span>            <span class=code-comment>//</span><span class=code-comment> Decrement the reference count
</span>            <span class=code-comment>//</span><span class=code-comment> if reference become zero delete the data
</span>            <span class=code-keyword>if</span>(reference-<span class=code-keyword>&gt;</span>Release() == <span class=code-digit>0</span>)
{
<span class=code-keyword>delete</span> pData;
<span class=code-keyword>delete</span> reference;
}
}
T&amp; <span class=code-keyword>operator</span>* ()
{
<span class=code-keyword>return</span> *pData;
}
T* <span class=code-keyword>operator</span>-<span class=code-keyword>&gt;</span> ()
{
<span class=code-keyword>return</span> pData;
}
SP<span class=code-keyword>&lt;</span>T<span class=code-keyword>&gt;</span>&amp; <span class=code-keyword>operator</span> = (<span class=code-keyword>const</span> SP<span class=code-keyword>&lt;</span>T<span class=code-keyword>&gt;</span>&amp; sp)
{
<span class=code-comment>//</span><span class=code-comment> Assignment operator
</span>            <span class=code-keyword>if</span> (<span class=code-keyword>this</span> != &amp;sp) <span class=code-comment>//</span><span class=code-comment> Avoid self assignment
</span>            {
<span class=code-comment>//</span><span class=code-comment> Decrement the old reference count
</span>                <span class=code-comment>//</span><span class=code-comment> if reference become zero delete the old data
</span>                <span class=code-keyword>if</span>(reference-<span class=code-keyword>&gt;</span>Release() == <span class=code-digit>0</span>)
{
<span class=code-keyword>delete</span> pData;
<span class=code-keyword>delete</span> reference;
}
<span class=code-comment>//</span><span class=code-comment> Copy the data and reference pointer
</span>                <span class=code-comment>//</span><span class=code-comment> and increment the reference count
</span>                pData = sp.pData;
reference = sp.reference;
reference-<span class=code-keyword>&gt;</span>AddRef();
}
<span class=code-keyword>return</span> *<span class=code-keyword>this</span>;
}
};
</pre>
Let us have a look at the client code.
<div class=SmallText id=premain9 style="WIDTH: 100%"><img id=preimg9 style="CURSOR: pointer" height=9 src="http://www.codeproject.com/images/minus.gif" width=9 preid="9"><span id=precollapse9 style="MARGIN-BOTTOM: 0px; CURSOR: pointer" preid="9"> Collapse</span><img style="MARGIN-LEFT: 35px" height=16 src="http://www.codeproject.com/images/copy_16.png" width=16><a href="http://www.codeproject.com/KB/cpp/SmartPointers.aspx#" preid="9"><u><font color=#800080> Copy Code</font></u></a></div>
<pre id=pre9 style="MARGIN-TOP: 0px">    <span class=code-keyword>void</span> main()
{
SP
<person> p(<span class=code-keyword>new</span> Person(<span class=code-string>"</span><span class=code-string>Scott"</span>, <span class=code-digit>25</span>));
p-<span class=code-keyword>&gt;</span>Display();
{
SP
<person> q = p;
q-<span class=code-keyword>&gt;</span>Display();
<span class=code-comment>//</span><span class=code-comment> Destructor of q will be called here..
</span>
SP
<person> r;
r = p;
r-<span class=code-keyword>&gt;</span>Display();
<span class=code-comment>//</span><span class=code-comment> Destructor of r will be called here..
</span>        }
p-<span class=code-keyword>&gt;</span>Display();
<span class=code-comment>//</span><span class=code-comment> Destructor of p will be called here
</span>        <span class=code-comment>//</span><span class=code-comment> and person pointer will be deleted
</span>    }
</pre>
When we create a smart pointer <code>p</code> of type <code>person</code>, the constructor of <code>SP</code> will be called, the data will be stored and a new <code>RC</code> pointer will be created. The <code>AddRef</code> method of <code>RC</code> is called to increment the reference count to 1. Now <code>SP
<person> q = p;</code> will create a new smart pointer <code>q</code> using the copy constructor, here the data will be copied and reference will again incremented to 2. Now <code>r = p; </code>will call the assignment operator to assign the value of <code>p</code> to <code>q</code>, here also we copy the data and increment the reference count, thus making the count 3. When <code>r</code> and <code>q</code> goes out of scope the destructors of respective objects will be called, here the reference count will be decremented, but data will not be deleted unless the reference count becomes zero, this happens only when destructor of <code>p</code> is called. Hence our data will be deleted only when no body is referring to it.
<h2>Applications </h2>
Memory leaks: Using smart pointers reduces work of managing pointers for memory leaks. Now you could create a pointer and forget about deleting it, the smart pointer will do that for you. This is the simplest garbage collector we could think off.
<p>Exceptions: Smart pointers are very useful where exceptions are used. For example look at the following code. </p>
<div class=SmallText id=premain10 style="WIDTH: 100%"><img id=preimg10 style="CURSOR: pointer" height=9 src="http://www.codeproject.com/images/minus.gif" width=9 preid="10"><span id=precollapse10 style="MARGIN-BOTTOM: 0px; CURSOR: pointer" preid="10"> Collapse</span><img style="MARGIN-LEFT: 35px" height=16 src="http://www.codeproject.com/images/copy_16.png" width=16><a href="http://www.codeproject.com/KB/cpp/SmartPointers.aspx#" preid="10"><u><font color=#800080> Copy Code</font></u></a></div>
<pre id=pre10 style="MARGIN-TOP: 0px">    <span class=code-keyword>void</span> MakeNoise()
{
Person* p = <span class=code-keyword>new</span> Person(<span class=code-string>"</span><span class=code-string>Scott"</span>, <span class=code-digit>25</span>);
p-<span class=code-keyword>&gt;</span>Shout();
<span class=code-keyword>delete</span> p;
}
</pre>
We are using a normal pointer here and deleting it after using, so every thing looks okay here. But what if our <code>Shout</code> function thows some exception <code><span class=code-keyword>delete</span> p;</code> will never be called. So we have a memory leak, let us handle that.
<div class=SmallText id=premain11 style="WIDTH: 100%"><img id=preimg11 style="CURSOR: pointer" height=9 src="http://www.codeproject.com/images/minus.gif" width=9 preid="11"><span id=precollapse11 style="MARGIN-BOTTOM: 0px; CURSOR: pointer" preid="11"> Collapse</span><img style="MARGIN-LEFT: 35px" height=16 src="http://www.codeproject.com/images/copy_16.png" width=16><a href="http://www.codeproject.com/KB/cpp/SmartPointers.aspx#" preid="11"><u><font color=#800080> Copy Code</font></u></a></div>
<pre id=pre11 style="MARGIN-TOP: 0px">    <span class=code-keyword>void</span> MakeNoise()
{
Person* p = <span class=code-keyword>new</span> Person(<span class=code-string>"</span><span class=code-string>Scott"</span>, <span class=code-digit>25</span>);
<span class=code-keyword>try</span>
{
p-<span class=code-keyword>&gt;</span>Shout();
}
<span class=code-keyword>catch</span>(...)
{
<span class=code-keyword>delete</span> p;
<span class=code-keyword>throw</span>;
}
<span class=code-keyword>delete</span> p;
}
</pre>
Don't you think this is a over head of catching an exception and rethrowing it? This code becomes cumbersome if you have many pointes created. How will a smart pointer help here, lets have a look at the same code if smart pointer is used.
<div class=SmallText id=premain12 style="WIDTH: 100%"><img id=preimg12 style="CURSOR: pointer" height=9 src="http://www.codeproject.com/images/minus.gif" width=9 preid="12"><span id=precollapse12 style="MARGIN-BOTTOM: 0px; CURSOR: pointer" preid="12"> Collapse</span><img style="MARGIN-LEFT: 35px" height=16 src="http://www.codeproject.com/images/copy_16.png" width=16><a href="http://www.codeproject.com/KB/cpp/SmartPointers.aspx#" preid="12"><u><font color=#800080> Copy Code</font></u></a></div>
<pre id=pre12 style="MARGIN-TOP: 0px">    <span class=code-keyword>void</span> MakeNoise()
{
SP<span class=code-keyword>&lt;</span>Person<span class=code-keyword>&gt;</span>
<person> p(<span class=code-keyword>new</span> Person(<span class=code-string>"</span><span class=code-string>Scott"</span>, <span class=code-digit>25</span>));
p-<span class=code-keyword>&gt;</span>Shout();
}
</pre>
We are making use of a smart pointer here; yes we don&#8217;t need to catch exception here. If the <code>Shout</code> method throws an exception stack unwinding will happen for the function and during this the destructor of all local object will be called, hence destructor of <code>p</code> will be called which will release the memory hence we are safe. So this makes it very useful to use smart pointers here.
<h2>Conclusion</h2>
Smart pointers are useful for writing safe and efficient code in C++. Make use of smart pointers and take the advantage of garbage collection. Take a look at Scott Meyers' auto_ptr implementation in STL. <!-- Article Ends --><!-- Main Page Contents End --></li>
<img src ="http://www.cppblog.com/iniwf/aggbug/76786.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/iniwf/" target="_blank">iniwf</a> 2009-03-16 22:15 <a href="http://www.cppblog.com/iniwf/archive/2009/03/16/76786.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Automatic Garbage Collection in C++ using Smart pointers</title><link>http://www.cppblog.com/iniwf/archive/2009/03/16/76784.html</link><dc:creator>iniwf</dc:creator><author>iniwf</author><pubDate>Mon, 16 Mar 2009 14:07:00 GMT</pubDate><guid>http://www.cppblog.com/iniwf/archive/2009/03/16/76784.html</guid><wfw:comment>http://www.cppblog.com/iniwf/comments/76784.html</wfw:comment><comments>http://www.cppblog.com/iniwf/archive/2009/03/16/76784.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/iniwf/comments/commentRss/76784.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/iniwf/services/trackbacks/76784.html</trackback:ping><description><![CDATA[<a href="http://www.codeproject.com/KB/cpp/automatic_gc_using_sp.aspx">http://www.codeproject.com/KB/cpp/automatic_gc_using_sp.aspx</a><br><br>
<h2>Introduction</h2>
<p>C++ is the most popular language around. Although many people have shifted to other high level languages like VB and Java, it is still the language of choice for system programming and the situations where performance can never be compromised.</p>
<p>C++ offers great features for dynamic memory allocation and de-allocation, but you can hardly find any C++ programmer who hasn&#8217;t been bugged by memory leaks in C++ programs. The reason is that in C++, you have to de-allocate memory yourself which is, at times, bug provoking.</p>
<p>Some high level languages like Java and C# provide automatic memory de-allocation facility. These languages have a built in Garbage Collector which looks for any memory which has no further reference in the program and de-allocates that memory. So programmers don&#8217;t have to worry about memory leaks. <strong>How about having Garbage Collection facility in C++ programs?</strong></p>
<p>Well, we can implement simple garbage collection facility in our programs using smart pointers, but it comes at some cost. There is a small overhead of an extra integer and a character variable per instance of classes for which you implement garbage collection. All source code for these garbage collection classes are provided with this article.</p>
<h2>What are smart pointers?</h2>
<p>I said we can implement garbage collection using &#8220;smart&#8221; pointers. But actually what are &#8220;smart&#8221; pointers?</p>
<p>C++ allows you to create &#8220;smart pointer&#8221; classes that encapsulate pointers, and override pointer operators to add new functionality to pointer operations. Template feature of C++ allows you to create generic wrappers to encapsulate pointers of almost any kind.</p>
<p>An example of smart pointers with templates could be a class which encapsulates double dimension arrays in C++.</p>
<div class=SmallText id=premain0 style="WIDTH: 100%"><img id=preimg0 style="CURSOR: pointer" height=9 src="http://www.codeproject.com/images/minus.gif" width=9 preid="0"><span id=precollapse0 style="MARGIN-BOTTOM: 0px; CURSOR: pointer" preid="0"> Collapse</span><img style="MARGIN-LEFT: 35px" height=16 src="http://www.codeproject.com/images/copy_16.png" width=16><a href="http://www.codeproject.com/KB/cpp/automatic_gc_using_sp.aspx#" preid="0"><u><font color=#800080> Copy Code</font></u></a></div>
<pre id=pre0 style="MARGIN-TOP: 0px"><span class=code-keyword>template</span><span class=code-keyword>&lt;</span> <span class=code-keyword>class</span> T<span class=code-keyword>&gt;</span> <span class=code-keyword>class</span> ArrayT
{
T** m_ptr; <span class=code-comment>//</span><span class=code-comment> for double dimension
</span>  <span class=code-keyword>int</span> sx,sy; <span class=code-comment>//</span><span class=code-comment> size of dimensions of array
</span>  <span class=code-keyword>public</span>:
ArrayT( <span class=code-keyword>int</span> dim1, <span class=code-keyword>int</span> dim2) <span class=code-comment>//</span><span class=code-comment> in case of ArrayT&lt;float&gt; b(10,20)
</span>  {
sx=dim1;sy=dim2;
m_ptr= <span class=code-keyword>new</span> T*[dim1];
<span class=code-keyword>for</span>( <span class=code-keyword>int</span> i=0;i<span class=code-keyword>&lt;</span>dim1;i++)
m_ptr[i]=new T[dim2];
}
T* <span class=code-keyword>operator</span>[] ( <span class=code-keyword>&lt;</span> pan class=cpp-keyword<span class=code-keyword>&gt;</span><span class=code-keyword>int</span> index)
{ <span class=code-keyword>return</span> m_ptr[index]; } <span class=code-comment>//</span><span class=code-comment> to add [] operator to ArrayT
</span>
~ArrayT()
{
<span class=code-keyword>for</span>( <span class=code-keyword>int</span> d=0;d<span class=code-keyword>&lt;</span>sx;d++)
<span class=code-keyword>delete</span> [] m_ptr[d];
<span class=code-keyword>delete</span> m_ptr;
}
};</pre>
<p>This class encapsulates the functionality of double dimension arrays for any object in C++. You can extend the functionality of 2D arrays in this manner. Using the same technique, you can also implement STL style resizable collection classes like vector.</p>
<p>Now, coming back to garbage collection using smart pointers, how can we use smart pointers for garbage collection within the class?</p>
<h2>What our Garbage Collector does?</h2>
<p>We are embedding the garbage collection feature within a particular class. This simple garbage collector de-allocates memory when an object is no longer referenced, hence preventing memory leaks. This is really simple to implement.</p>
<p>We are using reference counting mechanism. Whenever there is a new reference to an object, we increment the reference count, and when it is no longer referenced, i.e. reference count=0, we de allocate the memory.</p>
<h3>Implementation</h3>
<p>The template class <code>gcPtr<span class=code-keyword>&lt;</span>T<span class=code-keyword>&gt;</span></code> implements a garbage collecting pointer to any class derived from <code>RefCount</code> class.</p>
<div class=SmallText id=premain1 style="WIDTH: 100%"><img id=preimg1 style="CURSOR: pointer" height=9 src="http://www.codeproject.com/images/minus.gif" width=9 preid="1"><span id=precollapse1 style="MARGIN-BOTTOM: 0px; CURSOR: pointer" preid="1"> Collapse</span><img style="MARGIN-LEFT: 35px" height=16 src="http://www.codeproject.com/images/copy_16.png" width=16><a href="http://www.codeproject.com/KB/cpp/automatic_gc_using_sp.aspx#" preid="1"><u><font color=#800080> Copy Code</font></u></a></div>
<pre id=pre1 style="MARGIN-TOP: 0px"><span class=code-keyword>template</span> <span class=code-keyword>&lt;</span><span class=code-keyword>class</span> T<span class=code-keyword>&gt;</span><span class=code-keyword>class</span> RefCount
{
<span class=code-keyword>protected</span>:
<span class=code-keyword>int</span> refVal;
T* p;
<span class=code-keyword>public</span>:
RefCount(){ refVal=0; p=(T*)<span class=code-keyword>this</span>;}
<span class=code-keyword>void</span> AddRef() { refVal++; }
<span class=code-keyword>void</span> ReleaseRef()
{
refVal--;
<span class=code-keyword>if</span>(refVal == <span class=code-digit>0</span>)
<span class=code-keyword>delete</span> [] <span class=code-keyword>this</span>;
}
T* <span class=code-keyword>operator</span>-<span class=code-keyword>&gt;</span>(<span class=code-keyword>void</span>) { <span class=code-keyword>return</span> p; }
<span class=code-comment>//</span><span class=code-comment> Provide -&gt; operator for class inheriting
</span>
<span class=code-comment>//</span><span class=code-comment> RefCount
</span>  <span class=code-comment>//</span><span class=code-comment> Similarly you can add other overloaded
</span>  <span class=code-comment>//</span><span class=code-comment> operators in this class //so that
</span>  <span class=code-comment>//</span><span class=code-comment> you dont have to implement them again
</span>  <span class=code-comment>//</span><span class=code-comment> and again. //Once you have added
</span>  <span class=code-comment>//</span><span class=code-comment> these operators, they will be available
</span>  <span class=code-comment>//</span><span class=code-comment> to all classes // inheriting from RefCount
</span>  <span class=code-comment>//</span><span class=code-comment> to incorporate Garbage Collection.
</span>};</pre>
<p>This class implements simple reference counting. Any class which wishes to implement garbage collection should derive from this class. Note that <code>RefCount</code> takes a template parameter. This parameter is used to overload <code>-<span class=code-keyword>&gt;</span></code> operator for the class which inherits from <code>RefCount</code> class to implement garbage collection. I.e.,</p>
<div class=SmallText id=premain2 style="WIDTH: 100%"><img id=preimg2 style="CURSOR: pointer" height=9 src="http://www.codeproject.com/images/minus.gif" width=9 preid="2"><span id=precollapse2 style="MARGIN-BOTTOM: 0px; CURSOR: pointer" preid="2"> Collapse</span><img style="MARGIN-LEFT: 35px" height=16 src="http://www.codeproject.com/images/copy_16.png" width=16><a href="http://www.codeproject.com/KB/cpp/automatic_gc_using_sp.aspx#" preid="2"><u><font color=#800080> Copy Code</font></u></a></div>
<pre id=pre2 style="MARGIN-TOP: 0px">    <span class=code-keyword>class</span> foo : <span class=code-keyword>public</span> RefCount<span class=code-keyword>&lt;</span>foo<span class=code-keyword>&gt;</span><span class=code-keyword>&lt;</span>FOO<span class=code-keyword>&gt;</span>
{
};</pre>
<p><code>gcPtr</code> is a template class using smart pointers which encapsulates all garbage collection processes.</p>
<div class=SmallText id=premain3 style="WIDTH: 100%"><img id=preimg3 style="CURSOR: pointer" height=9 src="http://www.codeproject.com/images/minus.gif" width=9 preid="3"><span id=precollapse3 style="MARGIN-BOTTOM: 0px; CURSOR: pointer" preid="3"> Collapse</span><img style="MARGIN-LEFT: 35px" height=16 src="http://www.codeproject.com/images/copy_16.png" width=16><a href="http://www.codeproject.com/KB/cpp/automatic_gc_using_sp.aspx#" preid="3"><u><font color=#800080> Copy Code</font></u></a></div>
<pre id=pre3 style="MARGIN-TOP: 0px"><span class=code-keyword>template</span> <span class=code-keyword>&lt;</span><span class=code-keyword>class</span> T<span class=code-keyword>&gt;</span> <span class=code-keyword>class</span> gcPtr
{
T* ptr;
<span class=code-keyword>char</span> c;
<span class=code-keyword>public</span>:
gcPtr()
{
c=<span class=code-string>'</span><span class=code-string>0'</span>; <span class=code-comment>//</span><span class=code-comment> called when variable declare // as gcPtr&lt;foo&gt; a;
</span>  }
gcPtr(T* ptrIn)
{
ptr=ptrIn;
<span class=code-comment>//</span><span class=code-comment> called when variable declared
</span>    <span class=code-comment>//</span><span class=code-comment> as gcPtr&lt;foo&gt; a=new foo;
</span>    ptr-<span class=code-keyword>&gt;</span>AddRef();
c=<span class=code-string>'</span><span class=code-string>1'</span>;
}
<span class=code-comment>//</span><span class=code-comment> assuming we have variable gcPtr&lt;foo&gt; x
</span>  <span class=code-keyword>operator</span> T*(<span class=code-keyword>void</span>) { <span class=code-keyword>return</span> ptr; } <span class=code-comment>//</span><span class=code-comment>for x[]
</span>  T&amp; <span class=code-keyword>operator</span>*(<span class=code-keyword>void</span>) { <span class=code-keyword>return</span> *ptr; } <span class=code-comment>//</span><span class=code-comment> for *x type operations
</span>  T* <span class=code-keyword>operator</span>-<span class=code-keyword>&gt;</span>(<span class=code-keyword>void</span>){ <span class=code-keyword>return</span> ptr; } <span class=code-comment>//</span><span class=code-comment> for x-&gt; type operations
</span>  gcPtr&amp; operator=(gcPtr<span class=code-keyword>&lt;</span>T<span class=code-keyword>&gt;</span> &amp;pIn)
<span class=code-comment>//</span><span class=code-comment> for x=y where y is also gcPtr&lt;foo&gt; object
</span>  {
<span class=code-keyword>return</span> operator=((T *) pIn);
}
gcPtr&amp; operator=(T* pIn)
{
<span class=code-keyword>if</span>(c==<span class=code-string>'</span><span class=code-string>1'</span>)
<span class=code-comment>//</span><span class=code-comment> called by gcPtr&amp; operator=(gcPtr&lt;T&gt;&amp;pIn) in case of
</span>    { <span class=code-comment>//</span><span class=code-comment> assignment
</span>      <span class=code-comment>//</span><span class=code-comment> Decrease refcount for left hand side operand
</span>      ptr-<span class=code-keyword>&gt;</span>ReleaseRef();
<span class=code-comment>//</span><span class=code-comment> of &#8216;=&#8217; operator
</span>      ptr = pIn;
pIn-<span class=code-keyword>&gt;</span>AddRef(); <span class=code-comment>//</span><span class=code-comment> Increase reference count for the Right Hand
</span>      <span class=code-comment>//</span><span class=code-comment> operand of &#8216;=&#8217; operator
</span>      <span class=code-keyword>return</span> *<span class=code-keyword>this</span>;
}
<span class=code-keyword>else</span>
<span class=code-comment>//</span><span class=code-comment> if c=0 i.e variable was not allocated memory when // it was declared
</span>    { <span class=code-comment>//</span><span class=code-comment> like gcPtr&lt;foo&gt; x. in this case we //allocate memory using new
</span>      <span class=code-comment>//</span><span class=code-comment> operator, this will be called
</span>      ptr=pIn;
ptr-<span class=code-keyword>&gt;</span>AddRef();
<span class=code-keyword>return</span> *<span class=code-keyword>this</span>
}
}
~gcPtr(<span class=code-keyword>void</span>) { ptr-<span class=code-keyword>&gt;</span>ReleaseRef(); } <span class=code-comment>//</span><span class=code-comment> Decrement the refcount
</span>};</pre>
<p>Now, let&#8217;s see what happening in <code>gcPt</code> class template. There are two constructors. <code>gcPtr()</code> is for cases when you are just declaring the variable but not assigning memory to it using <code><span class=code-keyword>new</span></code> operator. <code>gcPtr(T*)</code> is for cases when you are assigning memory to <code>gcPtr</code> variable on declaration using <code><span class=code-keyword>new</span></code> operator. We have overloaded <code>T*</code> operator to provide support for array notation <code>[]</code>. This returns us the <code>T*</code> type pointer which our class is encapsulating. <code>-<span class=code-keyword>&gt;</span></code> operator is also overloaded to provide support for pointer operations like <code>x-<span class=code-keyword>&gt;</span>func()</code>. This operator also returns the <code>T*</code> pointer. An interesting thing is happening in the case of assignments like <code>x=y</code>. <code>gcPtr&amp; operator=(gcPtr<span class=code-keyword>&lt;</span>T<span class=code-keyword>&gt;</span> &amp;pIn)</code> function is called, which in turn calls <code>gcPtr&amp; operator=(T* pIn)</code> function, and only the &#8216;<code><span class=code-keyword>if</span></code>&#8217; block of this function is executed. Check this code:</p>
<div class=SmallText id=premain4 style="WIDTH: 100%"><img id=preimg4 style="CURSOR: pointer" height=9 src="http://www.codeproject.com/images/minus.gif" width=9 preid="4"><span id=precollapse4 style="MARGIN-BOTTOM: 0px; CURSOR: pointer" preid="4"> Collapse</span><img style="MARGIN-LEFT: 35px" height=16 src="http://www.codeproject.com/images/copy_16.png" width=16><a href="http://www.codeproject.com/KB/cpp/automatic_gc_using_sp.aspx#" preid="4"><u><font color=#800080> Copy Code</font></u></a></div>
<pre id=pre4 style="MARGIN-TOP: 0px">gcPtr&amp; operator=(gcPtr<span class=code-keyword>&lt;</span>T<span class=code-keyword>&gt;</span> &amp;pIn) <span class=code-comment>//</span><span class=code-comment> for x=y where y is also gcPtr&lt;foo&gt; object
</span>{
<span class=code-keyword>return</span> operator=((T *) pIn);
}</pre>
<p>We are type casting the input <code>gcPtr</code><t> parameter to <code>T*</code>. If <code>x=y</code> was the assignment (where <code>x</code> and <code>y</code> are variables of <code>gcPtr<span class=code-keyword>&lt;</span>FOO<span class=code-keyword>&gt;</span></code>), this means we are type casting <code>y</code> to <code>foo*</code> and calling <code>gcPtr&amp; operator=((foo*) y)</code> function. Now, let&#8217;s see how garbage collection mechanism is implemented in this function. Check this &#8216;<code><span class=code-keyword>if</span></code>&#8217; block code:</p>
<div class=SmallText id=premain5 style="WIDTH: 100%"><img id=preimg5 style="CURSOR: pointer" height=9 src="http://www.codeproject.com/images/minus.gif" width=9 preid="5"><span id=precollapse5 style="MARGIN-BOTTOM: 0px; CURSOR: pointer" preid="5"> Collapse</span><img style="MARGIN-LEFT: 35px" height=16 src="http://www.codeproject.com/images/copy_16.png" width=16><a href="http://www.codeproject.com/KB/cpp/automatic_gc_using_sp.aspx#" preid="5"><u><font color=#800080> Copy Code</font></u></a></div>
<pre id=pre5 style="MARGIN-TOP: 0px">  ptr-<span class=code-keyword>&gt;</span>ReleaseRef();
<span class=code-comment>//</span><span class=code-comment> Decrement the reference count for &#8216;x&#8217;. Now if the
</span>  <span class=code-comment>//</span><span class=code-comment>reference count is zero, memory for x will
</span>  <span class=code-comment>//</span><span class=code-comment> be de-allocated
</span>
ptr = pIn; <span class=code-comment>//</span><span class=code-comment> assign (foo*) y to ptr which is
</span>         <span class=code-comment>//</span><span class=code-comment>of type foo
</span>
pIn-<span class=code-keyword>&gt;</span>AddRef(); <span class=code-comment>//</span><span class=code-comment> Since we have made a new reference
</span>                   <span class=code-comment>//</span><span class=code-comment>to (foo*) y, increment
</span>                  <span class=code-comment>//</span><span class=code-comment>Reference count for (foo*)y
</span>
<span class=code-keyword>return</span> *<span class=code-keyword>this</span>; <span class=code-comment>//</span><span class=code-comment> return the x variable by reference.vv</span></pre>
<p>So, this explains how garbage collection is done when an object is no longer referenced.</p>
<h2>How to use Garbage collection in your project?</h2>
<p>Follow these steps to implement this simple garbage collection mechanism in your programs. It&#8217;s really simple.</p>
<ol>
    <li>Add <code>RefCount</code> and <code>gcPtr</code> classes to your project.
    <li>Derive your class from <code>RefCount</code>, passing the name of your class to <code>RefCount</code> as template parameter.
    <p>For example:</p>
    <div class=SmallText id=premain6 style="WIDTH: 100%"><img id=preimg6 style="CURSOR: pointer" height=9 src="http://www.codeproject.com/images/minus.gif" width=9 preid="6"><span id=precollapse6 style="MARGIN-BOTTOM: 0px; CURSOR: pointer" preid="6"> Collapse</span><img style="MARGIN-LEFT: 35px" height=16 src="http://www.codeproject.com/images/copy_16.png" width=16><a href="http://www.codeproject.com/KB/cpp/automatic_gc_using_sp.aspx#" preid="6"><u><font color=#800080> Copy Code</font></u></a></div>
    <pre id=pre6 style="MARGIN-TOP: 0px">   <span class=code-keyword>class</span> foo: <span class=code-keyword>public</span> RefCount<span class=code-keyword>&lt;</span>FOO<span class=code-keyword>&gt;</span><span class=code-keyword>&lt;</span>FOO<span class=code-keyword>&gt;</span>
    {
    <span class=code-keyword>public</span>:
    <span class=code-keyword>void</span> func() { AfxMessageBox(&#8220;Hello World&#8221;) };
    };</pre>
    <li>Now, to declare a pointer to your class, use <code>gcPtr <span class=code-keyword>&lt;</span>T<span class=code-keyword>&gt;</span></code> class, passing the name of your class as template parameter. <code>gcPtr<span class=code-keyword>&lt;</span>T<span class=code-keyword>&gt;</span></code> is a &#8220;smart&#8221; pointer. After allocating memory using <code><span class=code-keyword>new</span></code> operator in one of the methods shown below, you can use <code>gcPtr</code><t> just like your class pointer. It supports all pointer operations. You don&#8217;t need to de-allocate memory using <code><span class=code-keyword>delete</span></code> operator. It will be handled by <code>gcPtr</code> class.
    <p>&#160;</p>
    <div class=SmallText id=premain7 style="WIDTH: 100%"><img id=preimg7 style="CURSOR: pointer" height=9 src="http://www.codeproject.com/images/minus.gif" width=9 preid="7"><span id=precollapse7 style="MARGIN-BOTTOM: 0px; CURSOR: pointer" preid="7"> Collapse</span><img style="MARGIN-LEFT: 35px" height=16 src="http://www.codeproject.com/images/copy_16.png" width=16><a href="http://www.codeproject.com/KB/cpp/automatic_gc_using_sp.aspx#" preid="7"><u><font color=#800080> Copy Code</font></u></a></div>
    <pre id=pre7 style="MARGIN-TOP: 0px"><span class=code-comment>//</span><span class=code-comment>First Method
    </span>
    gcPtr<span class=code-keyword>&lt;</span>FOO<span class=code-keyword>&gt;</span> obj; <span class=code-comment>//</span><span class=code-comment> simple declaration
    </span>obj=new foo; <span class=code-comment>//</span><span class=code-comment> Assign memory to obj
    </span>obj-<span class=code-keyword>&gt;</span>func();
    <span class=code-comment>//</span><span class=code-comment>Second Method
    </span>gcPtr<span class=code-keyword>&lt;</span>FOO<span class=code-keyword>&gt;</span> obj=new obj;
    obj-<span class=code-keyword>&gt;</span>func();</pre>
    <li>You can also declare an array of your class using <code>gcPtr<span class=code-keyword>&lt;</span>T<span class=code-keyword>&gt;</span></code> class:
    <div class=SmallText id=premain8 style="WIDTH: 100%"><img id=preimg8 style="CURSOR: pointer" height=9 src="http://www.codeproject.com/images/minus.gif" width=9 preid="8"><span id=precollapse8 style="MARGIN-BOTTOM: 0px; CURSOR: pointer" preid="8"> Collapse</span><img style="MARGIN-LEFT: 35px" height=16 src="http://www.codeproject.com/images/copy_16.png" width=16><a href="http://www.codeproject.com/KB/cpp/automatic_gc_using_sp.aspx#" preid="8"><u><font color=#800080> Copy Code</font></u></a></div>
    <pre id=pre8 style="MARGIN-TOP: 0px">    gcPtr<span class=code-keyword>&lt;</span>FOO<span class=code-keyword>&gt;</span>obj= <span class=code-keyword>new</span> obj[<span class=code-digit>5</span>];
    obj[<span class=code-digit>2</span>]-<span class=code-keyword>&gt;</span>func();</pre>
    <p>=&gt; Memory will be de-allocated when your object is no longer referenced. For example:</p>
    <div class=SmallText id=premain9 style="WIDTH: 100%"><img id=preimg9 style="CURSOR: pointer" height=9 src="http://www.codeproject.com/images/minus.gif" width=9 preid="9"><span id=precollapse9 style="MARGIN-BOTTOM: 0px; CURSOR: pointer" preid="9"> Collapse</span><img style="MARGIN-LEFT: 35px" height=16 src="http://www.codeproject.com/images/copy_16.png" width=16><a href="http://www.codeproject.com/KB/cpp/automatic_gc_using_sp.aspx#" preid="9"><u><font color=#800080> Copy Code</font></u></a></div>
    <pre id=pre9 style="MARGIN-TOP: 0px">gcPtr<span class=code-keyword>&lt;</span>FOO<span class=code-keyword>&gt;</span> obj1=new obj;
    <span class=code-comment>//</span><span class=code-comment> increment reference count for obj1 i.e refcount=1
    </span> gcPtr<span class=code-keyword>&lt;</span>FOO<span class=code-keyword>&gt;</span> obj2=new obj; <span class=code-comment>//</span><span class=code-comment> increment reference count for obj2
    </span><span class=code-comment>//</span><span class=code-comment> i.e refcount=1
    </span> obj1=obj2; <span class=code-comment>//</span><span class=code-comment> decrement reference count for obj1
    </span><span class=code-comment>//</span><span class=code-comment>i.e refcount=0 and increment
    </span> <span class=code-comment>//</span><span class=code-comment> reference count for obj2 i.e refcount=2 . Memory will
    </span><span class=code-comment>//</span><span class=code-comment>be de-allocated
    </span> <span class=code-comment>//</span><span class=code-comment> for obj1. Now obj1 to the same memory as obj2
    </span> <span class=code-comment>//</span><span class=code-comment> When destructor for obj1 is called, it will decrement
    </span><span class=code-comment>//</span><span class=code-comment>the referencecount to 1, and
    </span><span class=code-comment>//</span><span class=code-comment>when destructor for obj2 is called, it will decrement it
    </span><span class=code-comment>//</span><span class=code-comment> to 0 and memory is de-allocated.</span></pre>
    </li>
</ol>
<p>That&#8217;s it. Isn&#8217;t it too simple to incorporate garbage collection and prevent memory leaks in C++? Of course; <strong>yes</strong>. What all you need is, to derive your class from <code>Refcount</code>.</p>
<h2>How to implement garbage collection for built in data types?</h2>
<p>To implement garbage collection for built-in data types like <code><span class=code-keyword>int</span></code>, <code><span class=code-keyword>float</span></code> etc., you can write a simple wrapper for them by overloading the operators.</p>
<div class=SmallText id=premain10 style="WIDTH: 100%"><img id=preimg10 style="CURSOR: pointer" height=9 src="http://www.codeproject.com/images/minus.gif" width=9 preid="10"><span id=precollapse10 style="MARGIN-BOTTOM: 0px; CURSOR: pointer" preid="10"> Collapse</span><img style="MARGIN-LEFT: 35px" height=16 src="http://www.codeproject.com/images/copy_16.png" width=16><a href="http://www.codeproject.com/KB/cpp/automatic_gc_using_sp.aspx#" preid="10"><u><font color=#800080> Copy Code</font></u></a></div>
<pre id=pre10 style="MARGIN-TOP: 0px"><span class=code-keyword>class</span> MyInt : <span class=code-keyword>public</span> gcPtr<span class=code-keyword>&lt;</span>MYINT<span class=code-keyword>&gt;</span>
{
<span class=code-keyword>public</span>:
<span class=code-keyword>int</span>* val;
..... <span class=code-comment>//</span><span class=code-comment> overloaded operators like ++,--,&gt; etc
</span>    ..... <span class=code-comment>//</span><span class=code-comment> or overload these operators in
</span>          <span class=code-comment>//</span><span class=code-comment>RefCount base class
</span><span class=code-comment>//</span><span class=code-comment> so that they will be available to any class inheriting
</span><span class=code-comment>//</span><span class=code-comment> incorporating garbage collection
</span>};</pre>
<p>Instead of every time adding all operator overloads in your class, you can once modify <code>RefCount</code> class and provide overloaded operators for <code>T</code> data type, as one overloaded operator is already provided there: i.e., <code>T* <span class=code-keyword>operator</span>-<span class=code-keyword>&gt;</span>(<span class=code-keyword>void</span>) { <span class=code-keyword>return</span> p; }</code>.</p>
<h2>Garbage collection in Action</h2>
<p>Now, let's see Garbage Collection in action in a simple MFC Dialog Box application. Run your program in Debug mode and start debugging. If I am using garbage collection, here is the output from the output window:</p>
<div class=SmallText id=premain11 style="WIDTH: 100%"><img id=preimg11 style="CURSOR: pointer" height=9 src="http://www.codeproject.com/images/minus.gif" width=9 preid="11"><span id=precollapse11 style="MARGIN-BOTTOM: 0px; CURSOR: pointer" preid="11"> Collapse</span><img style="MARGIN-LEFT: 35px" height=16 src="http://www.codeproject.com/images/copy_16.png" width=16><a href="http://www.codeproject.com/KB/cpp/automatic_gc_using_sp.aspx#" preid="11"><u><font color=#800080> Copy Code</font></u></a></div>
<pre lang=text id=pre11 style="MARGIN-TOP: 0px">    Loaded 'C:.DLL', no matching symbolic information found.
Loaded 'C:.DLL', no matching symbolic information found.
The thread 0x744 has exited with code 0 (0x0).
The program 'D:.exe' has exited with code 0 (0x0).</pre>
<p>There is no memory leak. Now, if I am neither doing garbage collection, nor I am manually deleting the object, here is the output:</p>
<div class=SmallText id=premain12 style="WIDTH: 100%"><img id=preimg12 style="CURSOR: pointer" height=9 src="http://www.codeproject.com/images/minus.gif" width=9 preid="12"><span id=precollapse12 style="MARGIN-BOTTOM: 0px; CURSOR: pointer" preid="12"> Collapse</span><img style="MARGIN-LEFT: 35px" height=16 src="http://www.codeproject.com/images/copy_16.png" width=16><a href="http://www.codeproject.com/KB/cpp/automatic_gc_using_sp.aspx#" preid="12"><u><font color=#800080> Copy Code</font></u></a></div>
<pre lang=text id=pre12 style="MARGIN-TOP: 0px">    Loaded 'C:.DLL', no matching symbolic information found.
Loaded 'C:.DLL', no matching symbolic information found.
Detected memory leaks!
Dumping objects -&gt;
{65} normal block at 0x002F2C80, 16 bytes long.
Data: &lt; ,/ &gt; 00 00 00 00 80 2C 2F 00 CD CD CD CD CD CD CD CD
Object dump complete.
The thread 0x50C has exited with code 0 (0x0).
The program 'D:.exe' has exited with code 0 (0x0).</pre>
<p>You can see the memory dumps. There is memory leak of 16 bytes.</p>
<p>I hope you enjoyed this article <font face=Wingdings size=2>J</font>. This is my first article on Code Project. Feel free to email me if you have any suggestions or if you have any problems using these classes + <strong>don&#8217;t forget to vote for me if you find this article useful :).</strong></p>
<!-- Article Ends --><!-- Main Page Contents End -->
<img src ="http://www.cppblog.com/iniwf/aggbug/76784.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/iniwf/" target="_blank">iniwf</a> 2009-03-16 22:07 <a href="http://www.cppblog.com/iniwf/archive/2009/03/16/76784.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Smart Pointers to boost your code</title><link>http://www.cppblog.com/iniwf/archive/2009/03/16/76782.html</link><dc:creator>iniwf</dc:creator><author>iniwf</author><pubDate>Mon, 16 Mar 2009 14:06:00 GMT</pubDate><guid>http://www.cppblog.com/iniwf/archive/2009/03/16/76782.html</guid><wfw:comment>http://www.cppblog.com/iniwf/comments/76782.html</wfw:comment><comments>http://www.cppblog.com/iniwf/archive/2009/03/16/76782.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/iniwf/comments/commentRss/76782.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/iniwf/services/trackbacks/76782.html</trackback:ping><description><![CDATA[<h2><a href="http://www.codeproject.com/KB/stl/boostsmartptr.aspx">http://www.codeproject.com/KB/stl/boostsmartptr.aspx</a></h2>
<h2>Contents</h2>
<p>Smart Pointers can greatly simplify C++ development. Chiefly, they provide automatic memory management close to more restrictive languages (like C# or VB), but there is much more they can do.</p>
<p><strong><a href="http://www.codeproject.com/KB/stl/boostsmartptr.aspx#Important Features"><font color=#800080><u>I already know smart pointers, but why should I use boost?</u></font></a></strong></p>
<ul>
    <li><a href="http://www.codeproject.com/KB/stl/boostsmartptr.aspx#What are Smart Pointers"><u><font color=#800080>What are Smart Pointers?</font></u></a>
    <li><a href="http://www.codeproject.com/KB/stl/boostsmartptr.aspx#The first: boost::scoped_ptrT"><u><font color=#800080>The first: boost::scoped_ptr&lt;T&gt;</font></u></a>
    <li><a href="http://www.codeproject.com/KB/stl/boostsmartptr.aspx#Reference counting pointers"><u><font color=#800080>Reference counting pointers</font></u></a>
    <ul>
        <li><a href="http://www.codeproject.com/KB/stl/boostsmartptr.aspx#Important Features"><font color=#800080><u>Important Features</u></font></a></li>
    </ul>
    <li><a href="http://www.codeproject.com/KB/stl/boostsmartptr.aspx#Example: Using shared_ptr in containers"><u><font color=#800080>Example: Using shared_ptr in containers</font></u></a>
    <li><a href="http://www.codeproject.com/KB/stl/boostsmartptr.aspx#What you absolutely must know to use boost smart pointers correctly"><u><font color=#800080>What you absolutely must know to use boost smart pointers correctly</font></u></a>
    <li><a href="http://www.codeproject.com/KB/stl/boostsmartptr.aspx#Cyclic References"><u><font color=#800080>Cyclic References</font></u></a>
    <li><a href="http://www.codeproject.com/KB/stl/boostsmartptr.aspx#Using weak_ptr to break cycles"><u><font color=#800080>Using weak_ptr to break cycles</font></u></a>
    <li><a href="http://www.codeproject.com/KB/stl/boostsmartptr.aspx#intrusive_ptr - lightweight shared pointer"><u><font color=#800080>intrusive_ptr - lightweight shared pointer</font></u></a>
    <li><a href="http://www.codeproject.com/KB/stl/boostsmartptr.aspx#scoped_array and shared_array"><u><font color=#800080>scoped_array and shared_array</font></u></a>
    <li><a href="http://www.codeproject.com/KB/stl/boostsmartptr.aspx#Installing Boost"><u><font color=#800080>Installing Boost</font></u></a>
    <ul>
        <li><a href="http://www.codeproject.com/KB/stl/boostsmartptr.aspx#Note about the sample project"><u><font color=#800080>Note about the sample project</font></u></a>
        <li><a href="http://www.codeproject.com/KB/stl/boostsmartptr.aspx#VC6: the min/max tragedy"><u><font color=#800080>VC6: the min/max tragedy</font></u></a> </li>
    </ul>
    <li><a href="http://www.codeproject.com/KB/stl/boostsmartptr.aspx#Resources"><u><font color=#800080>Resources</font></u></a> </li>
</ul>
<h2><a name="What are Smart Pointers">What are Smart Pointers?</a></h2>
<p>The name should already give it away:</p>
<blockquote>
<p><strong>A Smart Pointer is a C++ object that acts like a pointer, but additionally deletes the object when it is no longer needed.</strong></p>
</blockquote>
<p>"No longer needed" is hard to define, since resource management in C++ is very complex. Different smart pointer implementations cover the most common scenarios. Of course, different tasks than just deleting the object can be implemented too, but these applications are beyond the scope of this tutorial.</p>
<p>Many libraries provide smart pointer implementations with different advantages and drawbacks. The samples here use the <a href="http://www.boost.org/" target=_blank><u><font color=#0000ff>BOOST library</font></u></a>, a high quality open source template library, with many submissions considered for inclusion in the next C++ standard.</p>
<p>Boost provides the following smart pointer implementations:</p>
<table style="BORDER-COLLAPSE: collapse" borderColor=#111111 cellSpacing=0 cellPadding=0 width=600 border=1>
    <tbody>
        <tr>
            <td><code>shared_ptr<span class=code-keyword>&lt;</span>T<span class=code-keyword>&gt;</span></code></td>
            <td>pointer to <code>T<span class=code-string>"</span><span class=code-string></span></code> using a reference count to determine when the object is no longer needed. <code>shared_ptr</code> is the generic, most versatile smart pointer offered by boost.</td>
        </tr>
        <tr>
            <td><code>scoped_ptr<span class=code-keyword>&lt;</span>T<span class=code-keyword>&gt;</span></code></td>
            <td>a pointer automatically deleted when it goes out of scope. No assignment possible, but no performance penalties compared to "raw" pointers</td>
        </tr>
        <tr>
            <td><code>intrusive_ptr<span class=code-keyword>&lt;</span>T<span class=code-keyword>&gt;</span></code></td>
            <td>another reference counting pointer. It provides better performance than <code>shared_ptr</code>, but requires the type <code>T</code> to provide its own reference counting mechanism.</td>
        </tr>
        <tr>
            <td><code>weak_ptr<span class=code-keyword>&lt;</span>T<span class=code-keyword>&gt;</span></code></td>
            <td>a weak pointer, working in conjunction with <code>shared_ptr</code> to avoid circular references</td>
        </tr>
        <tr>
            <td><code>shared_array<span class=code-keyword>&lt;</span>T<span class=code-keyword>&gt;</span></code></td>
            <td>like <code>shared_ptr</code>, but access syntax is for an Array of <code>T</code></td>
        </tr>
        <tr>
            <td><code>scoped_array<span class=code-keyword>&lt;</span>T<span class=code-keyword>&gt;</span></code></td>
            <td>like <code>scoped_ptr</code>, but access syntax is for an Array of <code>T</code></td>
        </tr>
    </tbody>
</table>
<p>Let's start with the simplest one:</p>
<h2><a name="The first: boost::scoped_ptrT">The first: boost::scoped_ptr&lt;T&gt;</a></h2>
<p><code>scoped_ptr</code> is the simplest smart pointer provided by boost. It guarantees automatic deletion when the pointer goes out of scope.</p>
<blockquote>
<p>A note on the samples:</p>
<p>The samples use a helper class, <code>CSample</code>, that prints diagnostic messages when it it constructed, assigned, or destroyed. Still it might be interesting to step through with the debugger. The sample includes the required parts of boost, so no additional downloads are necessary - but please read the boost installations notes, below.</p>
</blockquote>
<p>The following sample uses a <code>scoped_ptr</code> for automatic destruction:</p>
<table style="BORDER-COLLAPSE: collapse" borderColor=#111111 cellPadding=2 width=600 border=1>
    <tbody>
        <tr>
            <td vAlign=top width="50%">Using normal pointers</td>
            <td vAlign=top width="50%">Using <code>scoped_ptr</code></td>
        </tr>
        <tr>
            <td vAlign=top width="50%">
            <div class=SmallText id=premain0 style="WIDTH: 100%"><img id=preimg0 style="CURSOR: pointer" height=9 src="http://www.codeproject.com/images/minus.gif" width=9 preid="0"><span id=precollapse0 style="MARGIN-BOTTOM: 0px; CURSOR: pointer" preid="0"> Collapse</span><img style="MARGIN-LEFT: 35px" height=16 src="http://www.codeproject.com/images/copy_16.png" width=16><a href="http://www.codeproject.com/KB/stl/boostsmartptr.aspx#" preid="0"><u><font color=#800080> Copy Code</font></u></a></div>
            <pre id=pre0 style="MARGIN-TOP: 0px"><strong>
            <span class=code-keyword>void</span> Sample1_Plain()</strong>
            {
            CSample * pSample(<span class=code-keyword>new</span> CSample);
            <span class=code-keyword>if</span> (!pSample-<span class=code-keyword>&gt;</span>Query() )
            <span class=code-comment>//</span><span class=code-comment> just some function...
            </span>  {
            <span class=code-keyword>delete</span> pSample;
            <span class=code-keyword>return</span>;
            }
            pSample-<span class=code-keyword>&gt;</span>Use();
            <span class=code-keyword>delete</span> pSample;
            }</pre>
            </td>
            <td vAlign=top width="50%">
            <div class=SmallText id=premain1 style="WIDTH: 100%"><img id=preimg1 style="CURSOR: pointer" height=9 src="http://www.codeproject.com/images/minus.gif" width=9 preid="1"><span id=precollapse1 style="MARGIN-BOTTOM: 0px; CURSOR: pointer" preid="1"> Collapse</span><img style="MARGIN-LEFT: 35px" height=16 src="http://www.codeproject.com/images/copy_16.png" width=16><a href="http://www.codeproject.com/KB/stl/boostsmartptr.aspx#" preid="1"><u><font color=#800080> Copy Code</font></u></a></div>
            <pre id=pre1 style="MARGIN-TOP: 0px"><span class=code-preprocessor>#include</span><span class=code-preprocessor> <span class=code-string>"</span><span class=code-string>boost/smart_ptr.h"</span><strong>
            </span>
            <span class=code-keyword>void</span> Sample1_ScopedPtr()</strong>
            {
            boost::scoped_ptr<span class=code-keyword>&lt;</span>CSample<span class=code-keyword>&gt;</span>
            samplePtr(<span class=code-keyword>new</span> CSample);
            <span class=code-keyword>if</span> (!samplePtr-<span class=code-keyword>&gt;</span>Query() )
            <span class=code-comment>//</span><span class=code-comment> just some function...
            </span>    <span class=code-keyword>return</span>;
            samplePtr-<span class=code-keyword>&gt;</span>Use();
            }</pre>
            </td>
        </tr>
    </tbody>
</table>
<p>Using "normal" pointers, we must remember to delete it at every place we exit the function. This is especially tiresome (and easily forgotten) when using exceptions. The second example uses a <code>scoped_ptr</code> for the same task. It automatically deletes the pointer when the function returns 8 even in the case of an exception thrown, which isn't even covered in the "raw pointer" sample!)</p>
<p>The advantage is obvious: in a more complex function, it's easy to forget to delete an object. <code>scoped_ptr</code> does it for you. Also, when dereferencing a <code>NULL</code> pointer, you get an assertion in debug mode.</p>
<table style="BORDER-COLLAPSE: collapse" borderColor=#111111 cellSpacing=0 cellPadding=0 border=1>
    <tbody>
        <tr>
            <td>use for</td>
            <td>automatic deletion of local objects or class members<sup>1</sup>, Delayed Instantiation, implementing PIMPL and RAII (see below)</td>
        </tr>
        <tr>
            <td>not good for</td>
            <td>element in an STL container, multiple pointers to the same object</td>
        </tr>
        <tr>
            <td>performance:</td>
            <td><code>scoped_ptr</code> adds little (if any) overhead to a "plain" pointer, it performs</td>
        </tr>
    </tbody>
</table>
<ol>
    <li><small>For this purpose, using <code>scoped_ptr</code> is more expressive than the (easy to misuse and more complex) <code>std::auto_ptr</code>: using <code>scoped_ptr</code>, you indicate that ownership transfer is not intended or allowed.</small></li>
</ol>
<h2><a name="Reference counting pointers">Reference counting pointers</a></h2>
<p><strong>Reference counting pointers</strong> track how many pointers are referring to an object, and when the last pointer to an object is destroyed, it deletes the object itself, too.</p>
<p>The "normal" reference counted pointer provided by boost is <code>shared_ptr</code> (the name indicates that multiple pointers can share the same object). Let's look at a few examples:</p>
<div class=SmallText id=premain2 style="WIDTH: 100%"><img id=preimg2 style="CURSOR: pointer" height=9 src="http://www.codeproject.com/images/minus.gif" width=9 preid="2"><span id=precollapse2 style="MARGIN-BOTTOM: 0px; CURSOR: pointer" preid="2"> Collapse</span><img style="MARGIN-LEFT: 35px" height=16 src="http://www.codeproject.com/images/copy_16.png" width=16><a href="http://www.codeproject.com/KB/stl/boostsmartptr.aspx#" preid="2"><u><font color=#800080> Copy Code</font></u></a></div>
<pre id=pre2 style="MARGIN-TOP: 0px"><strong><span class=code-keyword>void</span> Sample2_Shared()</strong>
{
<span class=code-comment>//</span><span class=code-comment> (A) create a new CSample instance with one reference
</span>  boost::shared_ptr<span class=code-keyword>&lt;</span>CSample<span class=code-keyword>&gt;</span> mySample(<span class=code-keyword>new</span> CSample);
printf(<span class=code-string>"</span><span class=code-string>The Sample now has %i references\n"</span>, mySample.use_count()); <span class=code-comment>//</span><span class=code-comment> should be 1
</span>
<span class=code-comment>//</span><span class=code-comment> (B) assign a second pointer to it:
</span>  boost::shared_ptr<span class=code-keyword>&lt;</span>CSample<span class=code-keyword>&gt;</span> mySample2 = mySample; <span class=code-comment>//</span><span class=code-comment> should be 2 refs by now
</span>  printf(<span class=code-string>"</span><span class=code-string>The Sample now has %i references\n"</span>, mySample.use_count());
<span class=code-comment>//</span><span class=code-comment> (C) set the first pointer to NULL
</span>  mySample.reset();
printf(<span class=code-string>"</span><span class=code-string>The Sample now has %i references\n"</span>, mySample2.use_count());  <span class=code-comment>//</span><span class=code-comment> 1
</span>
<span class=code-comment>//</span><span class=code-comment> the object allocated in (1) is deleted automatically
</span>  <span class=code-comment>//</span><span class=code-comment> when mySample2 goes out of scope
</span>}</pre>
<p>Line (A) creates a new <code>CSample</code> instance on the heap, and assigns the pointer to a <code>shared_ptr</code>, <code>mySample</code>. Things look like this:</p>
<p><img height=54 src="http://www.codeproject.com/KB/stl/boostsmartptr/image001.gif" width=343></p>
<p>Then, we assign it to a second pointer <code>mySample2</code>. Now, two pointers access the same data:</p>
<p><img height=78 src="http://www.codeproject.com/KB/stl/boostsmartptr/image002.gif" width=343></p>
<p>We reset the first pointer (equivalent to <code>p=NULL</code> for a raw pointer). The <code>CSample</code> instance is still there, since <code>mySample2</code> holds a reference to it:</p>
<p><img height=78 src="http://www.codeproject.com/KB/stl/boostsmartptr/image003.gif" width=343></p>
<p>Only when the last reference, <code>mySample2</code>, goes out of scope, the <code>CSample</code> is destroyed with it:</p>
<p><img height=78 src="http://www.codeproject.com/KB/stl/boostsmartptr/image004.gif" width=343></p>
<p>Of course, this is not limited to a single <code>CSample</code> instance, or two pointers, or a single function. Here are some use cases for a <code>shared_ptr</code>.</p>
<ul>
    <li>use in containers
    <li>using the pointer-to-implementation idiom (PIMPL)
    <li>Resource-Acquisition-Is-Initialization (RAII) idiom
    <li>Separating Interface from Implementation </li>
</ul>
<p><small><strong>Note</strong>: If you never heard of PIMPL (a.k.a. handle/body) or RAII, grab a good C++ book - they are important concepts every C++ programmer should know. Smart pointers are just one way to implement them conveniently in certain cases - discussing them here would break the limits of this article.</small></p>
<h3><a name="Important Features">Important Features</a></h3>
<p>The <code>boost::shared_ptr</code> implementation has some important features that make it stand out from other implementations:</p>
<ul>
    <li><strong><code>shared_ptr<span class=code-keyword>&lt;</span>T<span class=code-keyword>&gt;</span></code> works with an incomplete type:</strong>
    <p>When declaring or using a <code>shared_ptr<span class=code-keyword>&lt;</span>T<span class=code-keyword>&gt;</span></code>, <code>T</code> may be an "incomplete type". E.g., you do only a forward declaration using <code><span class=code-keyword>class</span> T;</code>. But do not yet define how <code>T</code> really looks like. Only where you dereference the pointer, the compiler needs to know "everything".</p>
    <li><strong><code>shared_ptr<span class=code-keyword>&lt;</span>T<span class=code-keyword>&gt;</span></code> works with any type:</strong>
    <p>There are virtually <strong>no</strong> requirements towards <code>T</code> (such as deriving from a base class).</p>
    <li><strong><code>shared_ptr<span class=code-keyword>&lt;</span>T<span class=code-keyword>&gt;</span></code> supports a custom deleter</strong>
    <p>So you can store objects that need a different cleanup than <code><span class=code-keyword>delete</span> p</code>. For more information, see the boost documentation.</p>
    <li><strong>Implicit conversion:</strong>
    <p>If a type <code>U *</code> can be implicitly converted to <code>T *</code> (e.g., because <code>T</code> is base class of <code>U</code>), a <code>shared_ptr<span class=code-keyword>&lt;</span>U<span class=code-keyword>&gt;</span></code> can also be converted to <code>shared_ptr<span class=code-keyword>&lt;</span>T<span class=code-keyword>&gt;</span></code> implicitly.</p>
    <li><strong><code>shared_ptr</code> is thread safe</strong>
    <p>(This is a design choice rather than an advantage, however, it is a necessity in multithreaded programs, and the overhead is low.)</p>
    <li><strong>Works on many platforms, proven and peer-reviewed</strong>, the usual things. </li>
</ul>
<h2><a name="Example: Using shared_ptr in containers">Example: Using shared_ptr in containers</a></h2>
<p>Many container classes, including the STL containers, require copy operations (e.g., when inserting an existing element into a list, vector, or container). However, when this copy operations are expensive (or are even unavailable), the typical solution is to use a container of pointers:</p>
<div class=SmallText id=premain3 style="WIDTH: 100%"><img id=preimg3 style="CURSOR: pointer" height=9 src="http://www.codeproject.com/images/minus.gif" width=9 preid="3"><span id=precollapse3 style="MARGIN-BOTTOM: 0px; CURSOR: pointer" preid="3"> Collapse</span><img style="MARGIN-LEFT: 35px" height=16 src="http://www.codeproject.com/images/copy_16.png" width=16><a href="http://www.codeproject.com/KB/stl/boostsmartptr.aspx#" preid="3"><u><font color=#800080> Copy Code</font></u></a></div>
<pre id=pre3 style="MARGIN-TOP: 0px">std::vector<span class=code-keyword>&lt;</span>CMyLargeClass *<span class=code-keyword>&gt;</span> vec;
vec.push_back( <span class=code-keyword>new</span> CMyLargeClass(<span class=code-string>"</span><span class=code-string>bigString"</span>) );</pre>
<p>However, this throws the task of memory management back to the caller. We can, however, use a <code>shared_ptr</code>:</p>
<div class=SmallText id=premain4 style="WIDTH: 100%"><img id=preimg4 style="CURSOR: pointer" height=9 src="http://www.codeproject.com/images/minus.gif" width=9 preid="4"><span id=precollapse4 style="MARGIN-BOTTOM: 0px; CURSOR: pointer" preid="4"> Collapse</span><img style="MARGIN-LEFT: 35px" height=16 src="http://www.codeproject.com/images/copy_16.png" width=16><a href="http://www.codeproject.com/KB/stl/boostsmartptr.aspx#" preid="4"><u><font color=#800080> Copy Code</font></u></a></div>
<pre id=pre4 style="MARGIN-TOP: 0px"><span class=code-keyword>typedef</span> boost::shared_ptr<span class=code-keyword>&lt;</span>CMyLargeClass<span class=code-keyword>&gt;</span>  CMyLargeClassPtr;
std::vector<span class=code-keyword>&lt;</span>CMyLargeClassPtr<span class=code-keyword>&gt;</span> vec;
vec.push_back( CMyLargeClassPtr(<span class=code-keyword>new</span> CMyLargeClass(<span class=code-string>"</span><span class=code-string>bigString"</span>)) );</pre>
<p>Very similar, but now, the elements get destroyed automatically when the vector is destroyed - unless, of course, there's another smart pointer still holding a reference. Let's have a look at sample 3:</p>
<div class=SmallText id=premain5 style="WIDTH: 100%"><img id=preimg5 style="CURSOR: pointer" height=9 src="http://www.codeproject.com/images/minus.gif" width=9 preid="5"><span id=precollapse5 style="MARGIN-BOTTOM: 0px; CURSOR: pointer" preid="5"> Collapse</span><img style="MARGIN-LEFT: 35px" height=16 src="http://www.codeproject.com/images/copy_16.png" width=16><a href="http://www.codeproject.com/KB/stl/boostsmartptr.aspx#" preid="5"><u><font color=#800080> Copy Code</font></u></a></div>
<pre id=pre5 style="MARGIN-TOP: 0px"><strong><span class=code-keyword>void</span> Sample3_Container()</strong>
{
<span class=code-keyword>typedef</span> boost::shared_ptr<span class=code-keyword>&lt;</span>CSample<span class=code-keyword>&gt;</span> CSamplePtr;
<span class=code-comment>//</span><span class=code-comment> (A) create a container of CSample pointers:
</span>  std::vector<span class=code-keyword>&lt;</span>CSamplePtr<span class=code-keyword>&gt;</span> vec;
<span class=code-comment>//</span><span class=code-comment> (B) add three elements
</span>  vec.push_back(CSamplePtr(<span class=code-keyword>new</span> CSample));
vec.push_back(CSamplePtr(<span class=code-keyword>new</span> CSample));
vec.push_back(CSamplePtr(<span class=code-keyword>new</span> CSample));
<span class=code-comment>//</span><span class=code-comment> (C) "keep" a pointer to the second:
</span>  CSamplePtr anElement = vec[<span class=code-digit>1</span>];
<span class=code-comment>//</span><span class=code-comment> (D) destroy the vector:
</span>  vec.clear();
<span class=code-comment>//</span><span class=code-comment> (E) the second element still exists
</span>  anElement-<span class=code-keyword>&gt;</span>Use();
printf(<span class=code-string>"</span><span class=code-string>done. cleanup is automatic\n"</span>);
<span class=code-comment>//</span><span class=code-comment> (F) anElement goes out of scope, deleting the last CSample instance
</span>}</pre>
<h2><a name="What you absolutely must know to use boost smart pointers correctly">What you absolutely must know to use boost smart pointers correctly</a></h2>
<p>A few things can go wrong with smart pointers (most prominent is an invalid reference count, which deletes the object too early, or not at all). The boost implementation promotes safety, making all "potentially dangerous" operations explicit. So, with a few rules to remember, you are safe.</p>
<p>There are a few rules you should (or must) follow, though:</p>
<p><strong>Rule 1: Assign and keep - </strong>Assign a newly constructed instance to a smart pointer immediately, and then keep it there. The smart pointer(s) now own the object, you must not delete it manually, nor can you take it away again. This helps to not accidentally delete an object that is still referenced by a smart pointer, or end up with an invalid reference count.</p>
<p><strong>Rule 2: a <code>_ptr<span class=code-keyword>&lt;</span>T<span class=code-keyword>&gt;</span></code> is not a <code>T *</code></strong> - more correctly, there are no implicit conversions between a <code>T *</code> and a smart pointer to type <code>T</code>.</p>
<p>This means:</p>
<ul>
    <li>When creating a smart pointer, you explicitly have to write <code>..._ptr<span class=code-keyword>&lt;</span>T<span class=code-keyword>&gt;</span> myPtr(<span class=code-keyword>new</span> T)</code>
    <li>You cannot assign a <code>T *</code> to a smart pointer
    <li>You cannot even write <code>ptr=NULL</code>. Use <code>ptr.reset()</code> for that.
    <li>To retrieve the raw pointer, use <code>ptr.get()</code>. Of course, you must not delete this pointer, or use it after the smart pointer it comes from is destroyed, reset or reassigned. Use <code>get()</code> only when you have to pass the pointer to a function that expects a raw pointer.
    <li>You cannot pass a <code>T *</code> to a function that expects a <code>_ptr<span class=code-keyword>&lt;</span>T<span class=code-keyword>&gt;</span></code> directly. You have to construct a smart pointer explicitly, which also makes it clear that you transfer ownership of the raw pointer to the smart pointer. (See also Rule 3.)
    <li>There is no generic way to find the smart pointer that "holds" a given raw pointer. However, the <a href="http://boost.org/libs/smart_ptr/sp_techniques.html" target=_blank><u><font color=#0000ff>boost: smart pointer programming techniques</font></u></a> illustrate solutions for many common cases. </li>
</ul>
<p><strong>Rule 2: No circular references</strong> - If you have two objects referencing each other through a reference counting pointer, they are never deleted. boost provides <code>weak_ptr</code> to break such cycles (see below).</p>
<p><strong>Rule 3: no temporary shared_ptr</strong> - Do not construct temporary <code>shared_ptr</code> to pass them to functions, always use a named (local) variable. (This makes your code safe in case of exceptions. See the <a href="http://boost.org/libs/smart_ptr/shared_ptr.htm" target=_blank><u><font color=#0000ff>boost: shared_ptr best practices</font></u></a> for a detailed explanation.)</p>
<h2><a name="Cyclic References">Cyclic References</a></h2>
<p>Reference counting is a convenient resource management mechanism, it has one fundamental drawback though: cyclic references are not freed automatically, and are hard to detect by the computer. The simplest example is this:</p>
<div class=SmallText id=premain6 style="WIDTH: 100%"><img id=preimg6 style="CURSOR: pointer" height=9 src="http://www.codeproject.com/images/minus.gif" width=9 preid="6"><span id=precollapse6 style="MARGIN-BOTTOM: 0px; CURSOR: pointer" preid="6"> Collapse</span><img style="MARGIN-LEFT: 35px" height=16 src="http://www.codeproject.com/images/copy_16.png" width=16><a href="http://www.codeproject.com/KB/stl/boostsmartptr.aspx#" preid="6"><u><font color=#800080> Copy Code</font></u></a></div>
<pre id=pre6 style="MARGIN-TOP: 0px"><span class=code-keyword>struct</span> CDad;
<span class=code-keyword>struct</span> CChild;
<span class=code-keyword>typedef</span> boost::shared_ptr<span class=code-keyword>&lt;</span>CDad<span class=code-keyword>&gt;</span>   CDadPtr;
<span class=code-keyword>typedef</span> boost::shared_ptr<span class=code-keyword>&lt;</span>CChild<span class=code-keyword>&gt;</span> CChildPtr;
<span class=code-keyword>struct</span> CDad : <span class=code-keyword>public</span> CSample
{
CChildPtr myBoy;
};
<span class=code-keyword>struct</span> CChild : <span class=code-keyword>public</span> CSample
{
CDadPtr myDad;
};
<span class=code-comment>//</span><span class=code-comment> a "thing" that holds a smart pointer to another "thing":
</span>
CDadPtr   parent(<span class=code-keyword>new</span> CDadPtr);
CChildPtr child(<span class=code-keyword>new</span> CChildPtr);
<span class=code-comment>//</span><span class=code-comment> deliberately create a circular reference:
</span>parent-<span class=code-keyword>&gt;</span>myBoy = child;
child-<span class=code-keyword>&gt;</span>myDad = dad;
<span class=code-comment>//</span><span class=code-comment> resetting one ptr...
</span>child.reset();</pre>
<p><code>parent</code> still references the <code>CDad</code> object, which itself references the <code>CChild</code>. The whole thing looks like this:</p>
<p><img height=78 src="http://www.codeproject.com/KB/stl/boostsmartptr/image005.gif" width=498></p>
<p>If we now call <code>dad.reset()</code>, we lose all "contact" with the two objects. But this leaves both with exactly one reference, and the shared pointers see no reason to delete either of them! We have no access to them anymore, but they mutually keep themselves "alive". This is a memory leak at best; in the worst case, the objects hold even more critical resources that are not released correctly.</p>
<p>The problem is not solvable with a "better" shared pointer implementation (or at least, only with unacceptable overhead and restrictions). So you have to break that cycle. There are two ways:</p>
<ol>
    <li>Manually break the cycle before you release your last reference to it
    <li>When the lifetime of <code>Dad</code> is known to exceed the lifetime of <code>Child</code>, the child can use a normal (raw) pointer to <code>Dad</code>.
    <li>Use a <code>boost::weak_ptr</code> to break the cycle. </li>
</ol>
<p>Solutions (1) and (2) are no perfect solutions, but they work with smart pointer libraries that do not offer a <code>weak_ptr</code> like boost does. But let's look at <code>weak_ptr</code> in detail:</p>
<h2><a name="Using weak_ptr to break cycles">Using weak_ptr to break cycles</a></h2>
<p><strong>Strong vs. Weak References</strong>:</p>
<p>A strong reference keeps the referenced object alive (i.e., as long as there is at least one strong reference to the object, it is not deleted). <code>boost::shared_ptr</code> acts as a strong reference. In contrast, a weak reference does not keep the object alive, it merely references it as long as it lives.</p>
<p>Note that a raw C++ pointer in this sense is a weak reference. However, if you have just the pointer, you have no ability to detect whether the object still lives.</p>
<p><code>boost::weak_ptr<span class=code-keyword>&lt;</span>T<span class=code-keyword>&gt;</span></code> is a smart pointer acting as weak reference. When you need it, you can request a strong (shared) pointer from it. (This can be <code>NULL</code> if the object was already deleted.) Of course, the strong pointer should be released immediately after use. In the above sample, we can decide to make one pointer weak:</p>
<div class=SmallText id=premain7 style="WIDTH: 100%"><img id=preimg7 style="CURSOR: pointer" height=9 src="http://www.codeproject.com/images/minus.gif" width=9 preid="7"><span id=precollapse7 style="MARGIN-BOTTOM: 0px; CURSOR: pointer" preid="7"> Collapse</span><img style="MARGIN-LEFT: 35px" height=16 src="http://www.codeproject.com/images/copy_16.png" width=16><a href="http://www.codeproject.com/KB/stl/boostsmartptr.aspx#" preid="7"><u><font color=#800080> Copy Code</font></u></a></div>
<pre id=pre7 style="MARGIN-TOP: 0px"><span class=code-keyword>struct</span> CBetterChild : <span class=code-keyword>public</span> CSample
{
weak_ptr<span class=code-keyword>&lt;</span>CDad<span class=code-keyword>&gt;</span> myDad;
<span class=code-keyword>void</span> BringBeer()
{
shared_ptr<span class=code-keyword>&lt;</span>CDad<span class=code-keyword>&gt;</span> strongDad = myDad.lock(); <span class=code-comment>//</span><span class=code-comment> request a strong pointer
</span>    <span class=code-keyword>if</span> (strongDad)                      <span class=code-comment>//</span><span class=code-comment> is the object still alive?
</span>      strongDad-<span class=code-keyword>&gt;</span>SetBeer();
<span class=code-comment>//</span><span class=code-comment> strongDad is released when it goes out of scope.
</span>    <span class=code-comment>//</span><span class=code-comment> the object retains the weak pointer
</span>  }
};</pre>
<p>See the Sample 5 for more.</p>
<h2><a name="intrusive_ptr - lightweight shared pointer">intrusive_ptr - lightweight shared pointer</a></h2>
<p><code>shared_ptr</code> offers quite some services beyond a "normal" pointer. This has a little price: the size of a shared pointer is larger than a normal pointer, and for each object held in a shared pointer, there is a tracking object holding the reference count and the deleter. In most cases, this is negligible.</p>
<p><code>intrusive_ptr</code> provides an interesting tradeoff: it provides the "lightest possible" reference counting pointer, if the object implements the reference count itself. This isn't so bad after all, when designing your own classes to work with smart pointers; it is easy to embed the reference count in the class itself, to get less memory footprint and better performance.</p>
<p>To use a type <code>T</code> with <code>intrusive_ptr</code>, you need to define two functions: <code>intrusive_ptr_add_ref</code> and <code>intrusive_ptr_release</code>. The following sample shows how to do that for a custom class:</p>
<div class=SmallText id=premain8 style="WIDTH: 100%"><img id=preimg8 style="CURSOR: pointer" height=9 src="http://www.codeproject.com/images/minus.gif" width=9 preid="8"><span id=precollapse8 style="MARGIN-BOTTOM: 0px; CURSOR: pointer" preid="8"> Collapse</span><img style="MARGIN-LEFT: 35px" height=16 src="http://www.codeproject.com/images/copy_16.png" width=16><a href="http://www.codeproject.com/KB/stl/boostsmartptr.aspx#" preid="8"><u><font color=#800080> Copy Code</font></u></a></div>
<pre id=pre8 style="MARGIN-TOP: 0px"><span class=code-preprocessor>#include</span><span class=code-preprocessor> <span class=code-string>"</span><span class=code-string>boost/intrusive_ptr.hpp"</span>
</span>
<span class=code-comment>//</span><span class=code-comment> forward declarations
</span><span class=code-keyword>class</span> CRefCounted;
<span class=code-keyword>namespace</span> boost
{
<span class=code-keyword>void</span> intrusive_ptr_add_ref(CRefCounted * p);
<span class=code-keyword>void</span> intrusive_ptr_release(CRefCounted * p);
};
<span class=code-comment>//</span><span class=code-comment> My Class
</span><span class=code-keyword>class</span> CRefCounted
{
<span class=code-keyword>private</span>:
<span class=code-keyword>long</span>    references;
<span class=code-keyword>friend</span> <span class=code-keyword>void</span> ::boost::intrusive_ptr_add_ref(CRefCounted * p);
<span class=code-keyword>friend</span> <span class=code-keyword>void</span> ::boost::intrusive_ptr_release(CRefCounted * p);
<span class=code-keyword>public</span>:
CRefCounted() : references(<span class=code-digit>0</span>) {}   <span class=code-comment>//</span><span class=code-comment> initialize references to 0
</span>};
<span class=code-comment>//</span><span class=code-comment> class specific addref/release implementation
</span><span class=code-comment>//</span><span class=code-comment> the two function overloads must be in the boost namespace on most compilers:
</span><span class=code-keyword>namespace</span> boost
{
<span class=code-keyword>inline</span> <span class=code-keyword>void</span> intrusive_ptr_add_ref(CRefCounted * p)
{
<span class=code-comment>//</span><span class=code-comment> increment reference count of object *p
</span>    ++(p-<span class=code-keyword>&gt;</span>references);
}
<span class=code-keyword>inline</span> <span class=code-keyword>void</span> intrusive_ptr_release(CRefCounted * p)
{
<span class=code-comment>//</span><span class=code-comment> decrement reference count, and delete object when reference count reaches 0
</span>   <span class=code-keyword>if</span> (--(p-<span class=code-keyword>&gt;</span>references) == <span class=code-digit>0</span>)
<span class=code-keyword>delete</span> p;
}
} <span class=code-comment>//</span><span class=code-comment> namespace boost</span></pre>
<p>This is the most simplistic (and not thread safe) implementation. However, this is such a common pattern, that it makes sense to provide a common base class for this task. Maybe another article ;)</p>
<h2><a name="scoped_array and shared_array">scoped_array and shared_array</a></h2>
<p>They are almost identical to <code>scoped_ptr</code> and <code>shared_ptr</code> - only they act like pointers to arrays, i.e., like pointers that were allocated using <code><span class=code-keyword>operator</span> <span class=code-keyword>new</span>[]</code>. They provide an overloaded <code><span class=code-keyword>operator</span>[]</code>. Note that neither of them knows the length initially allocated.</p>
<h2><a name="Installing Boost">Installing Boost</a></h2>
<p>Download the current boost version from <a href="http://www.boost.org/" target=_blank><u><font color=#0000ff>boost.org</font></u></a>, and unzip it to a folder of your choice. The unzipped sources use the following structure (using my folders):</p>
<table borderColor=#111111 cellSpacing=0 cellPadding=2 border=0>
    <tbody>
        <tr>
            <td><em>boost\</em></td>
            <td>the actual boost sources / headers</td>
        </tr>
        <tr>
            <td><em>doc\</em></td>
            <td>the documentation of the current version, in HTML format</td>
        </tr>
        <tr>
            <td><em>libs\</em></td>
            <td>libraries (not needed for </td>
        </tr>
        <tr>
            <td><code>....</code></td>
            <td>some more odd bits and ends ("more\" has some interesting stuff)</td>
        </tr>
    </tbody>
</table>
<p>I add this folder to the common includes of my IDE:</p>
<ul>
    <li>in VC6, this is <em>Tools/Options</em>, <em>Directories</em> tab, "<em>Show Directories for... Include files</em>",
    <li>in VC7, this is <em>Tools/Options</em>, then <em>Projects/VC++ directories</em>, "<em>Show Directories for... Include files</em>". </li>
</ul>
<p>Since the actual headers are in the <em>boost\</em> subfolder, my sources has <code><span class=code-preprocessor>#include</span><span class=code-preprocessor> <span class=code-string>"</span><span class=code-string>boost/smart_ptr.hpp"</span></span></code>. So everybody reading the source code knows immediately you are using boost smart pointers, not just any ones.</p>
<h3><a name="Note about the sample project">Note about the sample project</a></h3>
<p>The sample project contains a sub folder <em>boost\</em> with a <strong>selection</strong> of boost headers required. This is merely so you can download and compile the sample. You should really download the complete and most current sources (<a href="http://www.boost.org/" target=_blank><u><font color=#0000ff>now</font></u></a>!).</p>
<h3><a name="VC6: the min/max tragedy">VC6: the min/max tragedy</a></h3>
<p>There is a "little" problem with VC6 that makes using boost (and other libraries) a bit problematic out of the box.</p>
<p>The Windows header files define macros for <code>min</code> and <code>max</code>, and consequently, these respective functions are missing from the (original) STL implementation. Some Windows libraries such as MFC rely on <code>min</code>/<code>max</code> being present. Boost, however, expects <code>min</code> and <code>max</code> in the <code>std::</code> namespace. To make things worse, there is no feasible <code>min</code>/<code>max</code> template that accepts different (implicitly convertible) argument types, but some libraries rely on that.</p>
<p>boost tries to fix that as good as they can, but sometimes you will run into problems. If this happens, here's what I do: put the following code before the first <code>include</code>:</p>
<div class=SmallText id=premain9 style="WIDTH: 100%"><img id=preimg9 style="CURSOR: pointer" height=9 src="http://www.codeproject.com/images/minus.gif" width=9 preid="9"><span id=precollapse9 style="MARGIN-BOTTOM: 0px; CURSOR: pointer" preid="9"> Collapse</span><img style="MARGIN-LEFT: 35px" height=16 src="http://www.codeproject.com/images/copy_16.png" width=16><a href="http://www.codeproject.com/KB/stl/boostsmartptr.aspx#" preid="9"><u><font color=#800080> Copy Code</font></u></a></div>
<pre id=pre9 style="MARGIN-TOP: 0px"><span class=code-preprocessor>#define</span> _NOMINMAX            <span class=code-comment>//</span><span class=code-comment> disable windows.h defining min and max as macros
</span><span class=code-preprocessor>#include</span><span class=code-preprocessor> <span class=code-string>"</span><span class=code-string>boost/config.hpp"</span>  // include boosts compiler-specific <span class=code-string>"</span><span class=code-string>fixes"</span>
</span><span class=code-keyword>using</span> std::min;              <span class=code-comment>//</span><span class=code-comment> makle them globally available
</span><span class=code-keyword>using</span> std::max;</pre>
<p>This solution (as any other) isn't without problems either, but it worked in all cases I needed it, and it's just one place to put it.</p>
<h2><a name=Resources>Resources</a></h2>
<p>Not enough information? More Questions?</p>
<ul>
    <li><a href="http://www.boost.org/" target=_blank><u><font color=#0000ff>Boost home page</font></u></a>
    <li><a href="http://sourceforge.net/project/showfiles.php?group_id=7586" target=_blank><u><font color=#0000ff>Download boost</font></u></a>
    <li><a href="http://boost.org/libs/smart_ptr/smart_ptr.htm" target=_blank><u><font color=#0000ff>smart pointer overview</font></u></a> </li>
</ul>
<ul>
    <li>boost <a href="http://boost.org/more/mailing_lists.htm#users" target=_blank><u><font color=#0000ff>users mailing list</font></u></a>
    <p>Questions about boost? That's the place to go.</p>
    </li>
</ul>
<h4>Articles on Code Project:</h4>
<ul>
    <li><a href="http://www.codeproject.com/vcpp/stl/boostintro.asp"><u><font color=#0000ff>An Introduction to boost</font></u></a> by Andrew Walker
    <li><a href="http://www.codeproject.com/cpp/Designing_Robust_Objects.asp"><u><font color=#0000ff>Designing Robust Objects with boost</font></u></a> by Jim D'Agostino, a very interesting article: it seems to cover too much topics at once, but it excels at showing how different tools, mechanisms, paradigms, libraries, etc. work together. </li>
</ul>
<p><small>Please note: While I am happy about (almost) any feedback, please do not ask boost-specific questions here. Simply put, boost experts are unlikely to find your question here (and I'm just a boost noob). Of course, if you have questions, complaints, or recommendations regarding the article or the sample project, you are welcome.</small></p>
<img src ="http://www.cppblog.com/iniwf/aggbug/76782.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/iniwf/" target="_blank">iniwf</a> 2009-03-16 22:06 <a href="http://www.cppblog.com/iniwf/archive/2009/03/16/76782.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Boost中的智能指针</title><link>http://www.cppblog.com/iniwf/archive/2009/03/16/76765.html</link><dc:creator>iniwf</dc:creator><author>iniwf</author><pubDate>Mon, 16 Mar 2009 13:10:00 GMT</pubDate><guid>http://www.cppblog.com/iniwf/archive/2009/03/16/76765.html</guid><wfw:comment>http://www.cppblog.com/iniwf/comments/76765.html</wfw:comment><comments>http://www.cppblog.com/iniwf/archive/2009/03/16/76765.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/iniwf/comments/commentRss/76765.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/iniwf/services/trackbacks/76765.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 转自http://trailfire.com/quake_zh/marks/104701撰文&nbsp;Bjorn&nbsp;Karlsson&nbsp;翻译&nbsp;曾毅最后更新：2004年6月2日欢迎来到Boost,C++革新者出类拔萃的社群。如果你在C++标准库当中找不到你所需要的，很可能Boost已经为您准备好了他们的产品。&nbsp;Boost介绍&nbsp;根据Boost网站的介...&nbsp;&nbsp;<a href='http://www.cppblog.com/iniwf/archive/2009/03/16/76765.html'>阅读全文</a><img src ="http://www.cppblog.com/iniwf/aggbug/76765.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/iniwf/" target="_blank">iniwf</a> 2009-03-16 21:10 <a href="http://www.cppblog.com/iniwf/archive/2009/03/16/76765.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++基本功：全面掌握const、volatile和mutable关键字</title><link>http://www.cppblog.com/iniwf/archive/2009/03/16/76761.html</link><dc:creator>iniwf</dc:creator><author>iniwf</author><pubDate>Mon, 16 Mar 2009 12:06:00 GMT</pubDate><guid>http://www.cppblog.com/iniwf/archive/2009/03/16/76761.html</guid><wfw:comment>http://www.cppblog.com/iniwf/comments/76761.html</wfw:comment><comments>http://www.cppblog.com/iniwf/archive/2009/03/16/76761.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/iniwf/comments/commentRss/76761.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/iniwf/services/trackbacks/76761.html</trackback:ping><description><![CDATA[转自<a href="http://blog.csdn.net/RedStar81/archive/2003/09/14/19757.aspx">http://blog.csdn.net/RedStar81/archive/2003/09/14/19757.aspx</a><br><br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;C</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">程式设计过程中,const的使用可以频度是非常高的.它在保证程式安全方面起到了不可估量的作用.<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>用一句话来表达最确切不过了：&#8221;小兵立大功&#8221;.<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;有了const,那么mutable当然缺不了.<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;然作为const的同胞兄弟,volatile却在很多人的视野中消失.其实volatile担负的责任有何尝小呢</span><span style="COLOR: #000000">?</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;自然,它们的用法多样而灵巧,以至新手迷惑久久,下面就来系统的探讨总结一下吧：<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>一.一般应用<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">.const修饰各种变量的用法.<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;a.取代define<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">#define</span><span style="COLOR: #000000">&nbsp;D_INT&nbsp;100</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">#define</span><span style="COLOR: #000000">&nbsp;D_LONG&nbsp;100.29</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8230;&#8230;&#8230;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;D_INT&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">100</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;D_INT&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">100</span><span style="COLOR: #000000">;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">如果定义的int类型,可省略int.</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">long</span><span style="COLOR: #000000">&nbsp;D_LONG&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">100.29</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8230;&#8230;&#8230;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">&nbsp;a&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">100</span><span style="COLOR: #000000">;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;const替代define虽然增加分配空间,可它却保证了类型安全.<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;在C标准中,const定义的数据相当于全局的,而C</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">中视声明的位置而定.<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;b.修饰指针相关的变量<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;以三组简单的定义示意：<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Group1:&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;a&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;&nbsp;&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;b&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">a;</span><span style="COLOR: #000000">------------</span><span style="COLOR: #000000">&nbsp;&nbsp;[</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">b&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">a;</span><span style="COLOR: #000000">------------</span><span style="COLOR: #000000">&nbsp;&nbsp;[</span><span style="COLOR: #000000">2</span><span style="COLOR: #000000">]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;b&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">a;</span><span style="COLOR: #000000">----</span><span style="COLOR: #000000">&nbsp;[</span><span style="COLOR: #000000">4</span><span style="COLOR: #000000">]&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Group2:&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">p&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">const</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;</span><span style="COLOR: #000000">--------------</span><span style="COLOR: #000000">[</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">]&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">p&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">const</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;</span><span style="COLOR: #000000">--------------</span><span style="COLOR: #000000">[</span><span style="COLOR: #000000">2</span><span style="COLOR: #000000">]&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;p&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">const</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;</span><span style="COLOR: #000000">--------------</span><span style="COLOR: #000000">[</span><span style="COLOR: #000000">3</span><span style="COLOR: #000000">]&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;p&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">const</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;</span><span style="COLOR: #000000">----</span><span style="COLOR: #000000">[</span><span style="COLOR: #000000">4</span><span style="COLOR: #000000">]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Group3:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;a</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">b&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;a;</span><span style="COLOR: #000000">---------------</span><span style="COLOR: #000000">[</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">]<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">b&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;a;</span><span style="COLOR: #000000">---------------</span><span style="COLOR: #000000">[</span><span style="COLOR: #000000">2</span><span style="COLOR: #000000">]&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;b&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;a;</span><span style="COLOR: #000000">--------------</span><span style="COLOR: #000000">[</span><span style="COLOR: #000000">3</span><span style="COLOR: #000000">]&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">---&gt;修饰引用时,const被忽略</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;b&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;a;</span><span style="COLOR: #000000">-----</span><span style="COLOR: #000000">[</span><span style="COLOR: #000000">4</span><span style="COLOR: #000000">]<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;总结：<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">.如果const位于星号左侧,则const用来修饰指针所指向的变量,<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;即指针指向的为不可变的.<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">2</span><span style="COLOR: #000000">.如果const位于星号右侧,const就是修饰指针本身,即指针本身是<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;不可变的.<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;因此,[</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">]和[</span><span style="COLOR: #000000">2</span><span style="COLOR: #000000">]的情况相同,指针所指向内容不可变(const放在变量<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;声明符的位置无关),<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;这种情况下不允许对内容进行更改,如不能</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">a&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">3</span><span style="COLOR: #000000">&nbsp;;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">3</span><span style="COLOR: #000000">.[</span><span style="COLOR: #000000">3</span><span style="COLOR: #000000">]中指针本身是不可变的，而指针所指向的内容是可变的,这种情况<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;下不能对指针本身<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;进行更改操作,如a</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">是错误的<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">4</span><span style="COLOR: #000000">.[</span><span style="COLOR: #000000">4</span><span style="COLOR: #000000">]中指针本身和指向的内容均为常量.(引用特殊：引用在使用增加<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;遇义时,增加它代表的变量.所以qualifiers&nbsp;on&nbsp;reference&nbsp;are&nbsp;ignoredv.<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;延伸点:&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;注意示例:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">.</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">&nbsp;reference&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">1000</span><span style="COLOR: #000000">;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">2</span><span style="COLOR: #000000">.</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;p&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">const</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">*&amp;</span><span style="COLOR: #000000">&nbsp;q&nbsp;;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">2</span><span style="COLOR: #000000">.const在函数环境下的各种应用<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;常用法示例如下：<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;A</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">&nbsp;&nbsp;_Fun(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;&nbsp;A</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">&nbsp;_in);&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">修饰引用型传入参数<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;A&nbsp;&nbsp;_Fun(const&nbsp;A&amp;&nbsp;_in);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">A&amp;&nbsp;_Fun(const&nbsp;A&amp;&nbsp;_in);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">上面的两种,在函数内部有特殊的步骤,这里不详提了&#8230;..</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;&nbsp;A</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;&nbsp;_Fun(&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;&nbsp;A</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;_in);&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">修饰指针型传入参数</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;_Fun(&nbsp;)&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">修饰class成员函数</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;&nbsp;A</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">&nbsp;&nbsp;_Fun(A</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">&nbsp;_in&nbsp;);&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">修饰返回值</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;A&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">operator</span><span style="COLOR: #000000">(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;A</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">&nbsp;_in);&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">同时修饰传入参数和返回值</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;a.修饰参数<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;如void&nbsp;_Fun(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;A</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;_in)或&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;_Fun(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;A</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">&nbsp;_in);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;它们被修饰后,在函数执行期间行为特性同于上面的讲解,<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;注意：这不会改变原来数据的是否是const的属性.<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;b.修饰函数返回值<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;A</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">&nbsp;&nbsp;_Fun(&nbsp;)<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;A</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;_Fun(&nbsp;);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;注意：由于生命期不同步的问题,不可将局部的变量的指针或引用返回(static除外).<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;另外,传出来的视情况,代表不同的意思&#8230;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;对于A</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">返回类型,你若将之赋与其它变量,那么它实际执行的是将返回的变量<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;(或引用)代表的数据赋出..而你若将其它值赋予之,那么被赋予的是变量或引<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;用代表的数据.&nbsp;而const&nbsp;A</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">&nbsp;一般是防止之做为左值被赋值.<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;这个地方还有很多的细节问题(譬如在连续赋值、返回的临时对象的处理、<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;重载的const和非cosnt运算符等等),读者自己在实践中需要多多总结.<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>二、难点<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">3</span><span style="COLOR: #000000">.&nbsp;修饰类成员函数的const.<br><img id=Codehighlighter1_2583_2585_Open_Image onclick="this.style.display='none'; Codehighlighter1_2583_2585_Open_Text.style.display='none'; Codehighlighter1_2583_2585_Closed_Image.style.display='inline'; Codehighlighter1_2583_2585_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_2583_2585_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_2583_2585_Closed_Text.style.display='none'; Codehighlighter1_2583_2585_Open_Image.style.display='inline'; Codehighlighter1_2583_2585_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top>&nbsp;&nbsp;&nbsp;形如:</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;_Fun()&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;</span><span id=Codehighlighter1_2583_2585_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_2583_2585_Open_Text><span style="COLOR: #000000">{&nbsp;}</span></span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;你需要知道的几点规则：<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;a.const对象只能访问const成员函数,而非const对象可以访问任意<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;的成员函数,包括const成员函数.<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;b.const对象的成员是不可修改的,然而const对象通过指针维护的对象却<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;是可以修改的.<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;c.const成员函数不可以修改对象的数据,不管对象是否具有const性质.它在<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;编译时,以是否修改成员数据为依据,进行检查.<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;e.然而加上mutable修饰符的数据成员,对于任何情况下通过任何手段<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;都可修改,自然此时的const成员函数是可以修改它的&#8230;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">4</span><span style="COLOR: #000000">.谈谈volatile和&#8221;完全const对象&#8221;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;一个有volatile修饰的类只允许访问其接口的一个子集，这个子集由类的<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;实现者来控制.用户只有用const_cast才可以访问这个类型的全部接口.而且,<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;象const一样，类的volatile属性会传递给它的成员.想象const修饰的对<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;象,它的成员变量是不可修改的,而它通过指针维护的对象或原生变量是可<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;修改.那么我们想:如果对象维护一个char</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;,则它相当于char</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;chrptr&nbsp;;而不是const&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;cosnt&nbsp;chrptr;对于类中的指针你需要<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;这样修饰以防止它或它维护的资源：cosnt&nbsp;x</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;xptr;而不是x</span><span style="COLOR: #000000">*</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;xptr;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;因为cosnt&nbsp;修饰的对象它默认&nbsp;的行为是延续变量：x</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;cosnt&nbsp;xptr;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;更重要的,volatile修饰的数据,编译器不可对其进行执行期寄存于寄存器的优化.<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;这种特性,是为了多线程同步的需要.有兴趣者看参看Andrei的GP系列文章.<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">5</span><span style="COLOR: #000000">.谈谈const_cast转换运算符<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;这个关键字最基础的用法是：去掉数据的const性质.<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;值得注意的是：它只对指针、引用和其它的具有指向性质的类型.<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>参考：<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">.《Effective&nbsp;C</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">&nbsp;》关于const两种语义的论述<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">2</span><span style="COLOR: #000000">.Andrei&nbsp;Alexandrescu&nbsp;《</span><span style="COLOR: #0000ff">volatile</span><span style="COLOR: #000000">——编写多线程程序的好帮手》<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span></div>
<img src ="http://www.cppblog.com/iniwf/aggbug/76761.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/iniwf/" target="_blank">iniwf</a> 2009-03-16 20:06 <a href="http://www.cppblog.com/iniwf/archive/2009/03/16/76761.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++深度探索系列：智能指针(Smart Pointer) [二]</title><link>http://www.cppblog.com/iniwf/archive/2009/03/16/76759.html</link><dc:creator>iniwf</dc:creator><author>iniwf</author><pubDate>Mon, 16 Mar 2009 12:02:00 GMT</pubDate><guid>http://www.cppblog.com/iniwf/archive/2009/03/16/76759.html</guid><wfw:comment>http://www.cppblog.com/iniwf/comments/76759.html</wfw:comment><comments>http://www.cppblog.com/iniwf/archive/2009/03/16/76759.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/iniwf/comments/commentRss/76759.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/iniwf/services/trackbacks/76759.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 转自http://blog.csdn.net/RedStar81/archive/2003/03/21/19755.aspx主题索引：一、剖析C++标准库智能指针(std::auto_ptr)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1.Do&nbsp;you&nbsp;Smart&nbsp;Pointer?&nbsp;&nbsp;&nbs...&nbsp;&nbsp;<a href='http://www.cppblog.com/iniwf/archive/2009/03/16/76759.html'>阅读全文</a><img src ="http://www.cppblog.com/iniwf/aggbug/76759.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/iniwf/" target="_blank">iniwf</a> 2009-03-16 20:02 <a href="http://www.cppblog.com/iniwf/archive/2009/03/16/76759.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++深度探索系列：智能指针(Smart Pointer) [一]</title><link>http://www.cppblog.com/iniwf/archive/2009/03/16/76758.html</link><dc:creator>iniwf</dc:creator><author>iniwf</author><pubDate>Mon, 16 Mar 2009 12:00:00 GMT</pubDate><guid>http://www.cppblog.com/iniwf/archive/2009/03/16/76758.html</guid><wfw:comment>http://www.cppblog.com/iniwf/comments/76758.html</wfw:comment><comments>http://www.cppblog.com/iniwf/archive/2009/03/16/76758.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/iniwf/comments/commentRss/76758.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/iniwf/services/trackbacks/76758.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 转自http://blog.csdn.net/RedStar81/archive/2003/03/21/19754.aspx主题索引：一、剖析C++标准库智能指针(std::auto_ptr)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1.Do&nbsp;you&nbsp;Smart&nbsp;Pointer?&nbsp;&nbsp;&nbs...&nbsp;&nbsp;<a href='http://www.cppblog.com/iniwf/archive/2009/03/16/76758.html'>阅读全文</a><img src ="http://www.cppblog.com/iniwf/aggbug/76758.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/iniwf/" target="_blank">iniwf</a> 2009-03-16 20:00 <a href="http://www.cppblog.com/iniwf/archive/2009/03/16/76758.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>智能指针的代码实例</title><link>http://www.cppblog.com/iniwf/archive/2009/03/16/76756.html</link><dc:creator>iniwf</dc:creator><author>iniwf</author><pubDate>Mon, 16 Mar 2009 11:55:00 GMT</pubDate><guid>http://www.cppblog.com/iniwf/archive/2009/03/16/76756.html</guid><wfw:comment>http://www.cppblog.com/iniwf/comments/76756.html</wfw:comment><comments>http://www.cppblog.com/iniwf/archive/2009/03/16/76756.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/iniwf/comments/commentRss/76756.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/iniwf/services/trackbacks/76756.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 转自http://www.cppblog.com/martin/archive/2009/03/09/75988.aspx智能指针类用到的基类的定义:template&lt;typename&nbsp;T&gt;class&nbsp;HandleBase{public:&nbsp;&nbsp;&nbsp;&nbsp;typedef&nbsp;T&nbsp;element_type;&nbsp;...&nbsp;&nbsp;<a href='http://www.cppblog.com/iniwf/archive/2009/03/16/76756.html'>阅读全文</a><img src ="http://www.cppblog.com/iniwf/aggbug/76756.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/iniwf/" target="_blank">iniwf</a> 2009-03-16 19:55 <a href="http://www.cppblog.com/iniwf/archive/2009/03/16/76756.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>