﻿<?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++博客-再别流年的技术实验室-随笔分类-语言基础、数据结构与算法</title><link>http://www.cppblog.com/lf426/category/6366.html</link><description>Game Design Using C++ and SDL</description><language>zh-cn</language><lastBuildDate>Sat, 26 Jun 2010 21:39:42 GMT</lastBuildDate><pubDate>Sat, 26 Jun 2010 21:39:42 GMT</pubDate><ttl>60</ttl><item><title>彻底解密C++宽字符：6、国际化策略（完）</title><link>http://www.cppblog.com/lf426/archive/2010/06/26/118788.html</link><dc:creator>lf426</dc:creator><author>lf426</author><pubDate>Sat, 26 Jun 2010 11:55:00 GMT</pubDate><guid>http://www.cppblog.com/lf426/archive/2010/06/26/118788.html</guid><wfw:comment>http://www.cppblog.com/lf426/comments/118788.html</wfw:comment><comments>http://www.cppblog.com/lf426/archive/2010/06/26/118788.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/lf426/comments/commentRss/118788.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/lf426/services/trackbacks/118788.html</trackback:ping><description><![CDATA[<a title="<本文pdf文档下载>" href="http://www.163pan.com/files/c0x000k09.html" href_cetemp="http://www.163pan.com/files/c0x000k09.html">&lt;本文PDF文档下载&gt;</a><br><br>硬编码的硬伤<br><br>我们现在知道，C/C++的宽窄转换是依赖系统的locale的，并且在运行时完成。考虑这样一种情况，我们在简体中文Windows下编译如下语句：<br>const char* s = "中文abc";<br>根据我们之前的讨论，编译器将按照Windows Codepage936（GB2312）对这个字符串进行编码。如果我们在程序中运行宽窄转换函数，将s转换为宽字符串ws，如果这个程序运行在简体中文环境下是没问题的，将执行从GB2312到UCS-2BE的转换；但是，如果在其他语言环境下，比如是繁体中文BIG5，程序将根据系统的locale执行从BIG5到UCS-2BE的转换，这显然就出现了错误。<br><br>补救<br><br>有没有补救这个问题的办法呢？一个解决方案就是执行不依赖locale的宽窄转换。实际上，这就已经不是宽窄转换之间的问题了，而是编码之间转换的问题了。我们可以用GNU的libiconv实现任意编码间的转换，对于以上的具体情况，指明是从GB2312到UCS-2BE就不会出错。（请参考本人前面的章节：<a title=win32下的libiconv href="http://www.cppblog.com/lf426/archive/2008/03/30/45738.html">win32下的libiconv</a>），但这显然是一个笨拙的策略：我们在简体中文Windows下必须使用GB2312到UCS-2BE版本的宽窄转换函数；到了BIG5环境下，就必须重新写从BIG5到UCS-2BE的宽窄转换函数。<br><br>Windows的策略<br><br>Windows的策略是淘汰了窄字符串，干脆只用宽字符串。所有的硬编码全部加上特定宏，比如TEXT()，如果程序是所谓Unicode编译，在编译时就翻译为UCS2-BE——Windows自称为Unicode编程，其本质是使用了UCS-2BE的16位宽字符串。<br><br>Linux的策略<br><br>Linux下根本就不存在这个问题！因为各种语言的Linux都使用UTF-8的编码，所以，无论系统locale如何变化，窄到宽转换的规则一直是UTF-8到UTF32-BE 。<br><br>跨平台策略<br><br>因为在16位的范围内，UTF32-BE的前16位为0，后16位与UCS2-BE是一样的，所以，即使wchar_t的sizeof()不一样，在一般情况下，跨平台使用宽字符（串）也应该是兼容的。但是依然存在潜在的问题，就是那些4字节的UTF32编码。<br><br>gettext策略<br><br>以上都是将ASCII及以外的编码硬编码在程序中的办法。GNU的gettext提供了另外一种选择：在程序中只硬编码ASCII，多语言支持由gettext函数库在运行时加载。（对gettext的介绍请参考本人前面的章节：<a title=Win32下的GetText href="http://www.cppblog.com/lf426/archive/2008/03/30/45723.html">Win32下的GetText</a>）。gettext的多语言翻译文件不在程序中，而是单独的提出来放在特定的位置。gettext明确的知道这些翻译文件的编码，所以可以准确的告诉给系统翻译的正确信息，而系统将这些信息以当前的系统locale编码成窄字符串反馈给程序。例如，在简体中文Windows中，gettext的po文件也可以以UTF-8储存，gettext将po文件翻译成mo文件，确保mo文件在任何系统和语言环境下都能够正确翻译。在运行是传给win32程序的窄串符合当前locale，是GB2312。gettext让国际化的翻译更加的方便，缺点是目前我没找到支持宽字符串的版本（据说是有ugettext()支持宽字符串），所以要使用gettext只能使用窄字符串。但是gettext可以转换到宽字符串，而且不会出现宽窄转换的问题，因为gettext是运行时根据locale翻译的。例如：<br>const char* s = gettext("Chinese a b c");<br>其中"Chinese a b c"在po中的翻译是"中文abc"<br>使用依赖locale的运行时宽窄转换函数：<br>const std::wstring wstr = s2ws(s);<br>运行时调用该po文件对应的mo文件，在简体中文环境下就以GB2312传给程序，在繁体中文中就以BIG5传给程序，这样s2ws()总能够正常换算编码。<br><br>更多<br><br>在本文的最后，我想回到C++的stream问题上。用fstream转换如此的简单，sstream却不支持。改造一个支持codecvt的string stream需要改造basic_stringbuf。basic_stringbuf和basic_filebuf都派生自basic_streambuf，所不同的是basic_filebuf在构造和open()的时候调用了codecvt，只需要在basic_stringbuf中添加这个功能就可以了。说起来容易，实际上是需要重新改造一个STL模板，尽管这些模板源代码都是在标准库头文件中现成的，但是我还是水平有限，没有去深究了。另外一个思路是构建一个基于内存映射的虚拟文件，这个框架在boost的iostreams库中，有兴趣的朋友可以深入的研究。<br>（完） 
<img src ="http://www.cppblog.com/lf426/aggbug/118788.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/lf426/" target="_blank">lf426</a> 2010-06-26 19:55 <a href="http://www.cppblog.com/lf426/archive/2010/06/26/118788.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>彻底解密C++宽字符：5、利用fstream转换</title><link>http://www.cppblog.com/lf426/archive/2010/06/26/118779.html</link><dc:creator>lf426</dc:creator><author>lf426</author><pubDate>Sat, 26 Jun 2010 08:40:00 GMT</pubDate><guid>http://www.cppblog.com/lf426/archive/2010/06/26/118779.html</guid><wfw:comment>http://www.cppblog.com/lf426/comments/118779.html</wfw:comment><comments>http://www.cppblog.com/lf426/archive/2010/06/26/118779.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/lf426/comments/commentRss/118779.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/lf426/services/trackbacks/118779.html</trackback:ping><description><![CDATA[<a title="<本文pdf文档下载>" href="http://www.163pan.com/files/c0x000k09.html" href_cetemp="http://www.163pan.com/files/c0x000k09.html">&lt;本文PDF文档下载&gt;</a><br><br>C++的流和本地化策略集<br><br>BS在设计C++流的时候希望其具备智能化，并且是可扩展的智能化，也就是说，C++的流可以&#8220;读懂&#8221;一些内容。比如：<br>
<div style="BORDER-BOTTOM: #cccccc 1px solid; BORDER-LEFT: #cccccc 1px solid; PADDING-BOTTOM: 4px; BACKGROUND-COLOR: #eeeeee; PADDING-LEFT: 4px; WIDTH: 98%; PADDING-RIGHT: 5px; FONT-SIZE: 13px; WORD-BREAK: break-all; BORDER-TOP: #cccccc 1px solid; BORDER-RIGHT: #cccccc 1px solid; PADDING-TOP: 4px"><span style="COLOR: #000000">std::cout&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">123</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">ok</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;std::endl;</span></div>
这句代码中，std::cout是能判断出123是int而"ok"是const char[3]。利用流的智能，甚至可以做一些基础类型的转换，比如从int到string，string到int：<br>
<div style="BORDER-BOTTOM: #cccccc 1px solid; BORDER-LEFT: #cccccc 1px solid; PADDING-BOTTOM: 4px; BACKGROUND-COLOR: #eeeeee; PADDING-LEFT: 4px; WIDTH: 98%; PADDING-RIGHT: 5px; FONT-SIZE: 13px; WORD-BREAK: break-all; BORDER-TOP: #cccccc 1px solid; BORDER-RIGHT: #cccccc 1px solid; PADDING-TOP: 4px"><span style="COLOR: #000000">std::</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">&nbsp;str(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">123</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br>std::stringstream&nbsp;sstr(str);<br></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;i;<br>sstr&nbsp;</span><span style="COLOR: #000000">&gt;&gt;</span><span style="COLOR: #000000">&nbsp;i;</span></div>
<div style="BORDER-BOTTOM: #cccccc 1px solid; BORDER-LEFT: #cccccc 1px solid; PADDING-BOTTOM: 4px; BACKGROUND-COLOR: #eeeeee; PADDING-LEFT: 4px; WIDTH: 98%; PADDING-RIGHT: 5px; FONT-SIZE: 13px; WORD-BREAK: break-all; BORDER-TOP: #cccccc 1px solid; BORDER-RIGHT: #cccccc 1px solid; PADDING-TOP: 4px"><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;i&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">123</span><span style="COLOR: #000000">;<br>std::stringstream&nbsp;sstr;<br>sstr&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;i;<br>std::</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">&nbsp;str&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;sstr.str();</span></div>
尽管如此，C++并不满足，C++甚至希望流能&#8220;明白&#8221;时间，货币的表示法。而时间和货币的表示方法在世界范围内是不同的，所以，每一个流都有自己的locale在影响其行为，C++中叫做激活（imbue，也有翻译成浸染）。而我们知道，每一个locale都有多个facet，这些facet并非总是被use_facet使用的。决定使用哪些facet的，是流的缓存basic_streambuf及其派生类basic_stringbuf和basic_filebuf。我们要用到的facet是codecvt，这个facet只被basic_filebuf使用——这就是为什么只能用fstream来实现宽窄转换，而无法使用sstream来实现的原因。<br>头文件：<br>
<div style="BORDER-BOTTOM: #cccccc 1px solid; BORDER-LEFT: #cccccc 1px solid; PADDING-BOTTOM: 4px; BACKGROUND-COLOR: #eeeeee; PADDING-LEFT: 4px; WIDTH: 98%; PADDING-RIGHT: 5px; FONT-SIZE: 13px; WORD-BREAK: break-all; BORDER-TOP: #cccccc 1px solid; BORDER-RIGHT: #cccccc 1px solid; PADDING-TOP: 4px"><span style="COLOR: #008000">//</span><span style="COLOR: #008000">filename&nbsp;string_wstring_fstream.hpp</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">#ifndef&nbsp;STRING_WSTRING_FSTREAM_HPP<br></span><span style="COLOR: #0000ff">#define</span><span style="COLOR: #000000">&nbsp;STRING_WSTRING_FSTREAM_HPP</span><span style="COLOR: #000000"><br><br>#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><br></span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;std::wstring&nbsp;s2ws(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;std::</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">&nbsp;s);<br></span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;std::</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">&nbsp;ws2s(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;std::wstring</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">&nbsp;s);<br><br></span><span style="COLOR: #0000ff">#endif</span></div>
实现：<br>
<div style="BORDER-BOTTOM: #cccccc 1px solid; BORDER-LEFT: #cccccc 1px solid; PADDING-BOTTOM: 4px; BACKGROUND-COLOR: #eeeeee; PADDING-LEFT: 4px; WIDTH: 98%; PADDING-RIGHT: 5px; FONT-SIZE: 13px; WORD-BREAK: break-all; BORDER-TOP: #cccccc 1px solid; BORDER-RIGHT: #cccccc 1px solid; PADDING-TOP: 4px"><span style="COLOR: #000000">#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br>#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">fstream</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br>#include&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">string_wstring_fstream.hpp</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"><br><br></span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;std::wstring&nbsp;s2ws(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;std::</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">&nbsp;s)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;std::locale&nbsp;sys_loc(</span><span style="COLOR: #000000">""</span><span style="COLOR: #000000">);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;std::ofstream&nbsp;ofs(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">cvt_buf</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br>&nbsp;&nbsp;&nbsp;&nbsp;ofs&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;s;<br>&nbsp;&nbsp;&nbsp;&nbsp;ofs.close();<br><br>&nbsp;&nbsp;&nbsp;&nbsp;std::wifstream&nbsp;wifs(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">cvt_buf</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br>&nbsp;&nbsp;&nbsp;&nbsp;wifs.imbue(sys_loc);<br>&nbsp;&nbsp;&nbsp;&nbsp;std::wstring&nbsp;wstr;<br>&nbsp;&nbsp;&nbsp;&nbsp;wifs&nbsp;</span><span style="COLOR: #000000">&gt;&gt;</span><span style="COLOR: #000000">&nbsp;wstr;<br>&nbsp;&nbsp;&nbsp;&nbsp;wifs.close();<br><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;wstr;<br>}<br><br></span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;std::</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">&nbsp;ws2s(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;std::wstring</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">&nbsp;s)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;std::locale&nbsp;sys_loc(</span><span style="COLOR: #000000">""</span><span style="COLOR: #000000">);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;std::wofstream&nbsp;wofs(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">cvt_buf</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br>&nbsp;&nbsp;&nbsp;&nbsp;wofs.imbue(sys_loc);<br>&nbsp;&nbsp;&nbsp;&nbsp;wofs&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;s;<br>&nbsp;&nbsp;&nbsp;&nbsp;wofs.close();<br><br>&nbsp;&nbsp;&nbsp;&nbsp;std::ifstream&nbsp;ifs(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">cvt_buf</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br>&nbsp;&nbsp;&nbsp;&nbsp;std::</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">&nbsp;str;<br>&nbsp;&nbsp;&nbsp;&nbsp;ifs&nbsp;</span><span style="COLOR: #000000">&gt;&gt;</span><span style="COLOR: #000000">&nbsp;str;<br>&nbsp;&nbsp;&nbsp;&nbsp;ifs.close();<br><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;str;<br>}</span></div>
在窄到宽的转化中，我们先使用默认的本地化策略集（locale）将s通过窄文件流ofs传入文件，这是char到char的传递，没有任何转换；然后我们打开宽文件流wifs，并用系统的本地化策略集（locale）去激活（imbue）之，流在读回宽串wstr的时候，就是char到wchar_t的转换，并且因为激活了sys_loc，所以实现标准窄到宽的转换。<br>在宽到窄的转化中，我们先打开的是宽文件流wofs，并且用系统的本地化策略集sys_loc激活（imbue）之，这时候，因为要写的文件cvt_buf是一个外部编码，所以执行了从wchar_t到char的标准转换。读回来的文件流从char到char，不做任何转换。 
<img src ="http://www.cppblog.com/lf426/aggbug/118779.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/lf426/" target="_blank">lf426</a> 2010-06-26 16:40 <a href="http://www.cppblog.com/lf426/archive/2010/06/26/118779.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>彻底解密C++宽字符：4、利用codecvt和use_facet转换</title><link>http://www.cppblog.com/lf426/archive/2010/06/26/118772.html</link><dc:creator>lf426</dc:creator><author>lf426</author><pubDate>Sat, 26 Jun 2010 05:39:00 GMT</pubDate><guid>http://www.cppblog.com/lf426/archive/2010/06/26/118772.html</guid><wfw:comment>http://www.cppblog.com/lf426/comments/118772.html</wfw:comment><comments>http://www.cppblog.com/lf426/archive/2010/06/26/118772.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/lf426/comments/commentRss/118772.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/lf426/services/trackbacks/118772.html</trackback:ping><description><![CDATA[<a title="<本文pdf文档下载>" href="http://www.163pan.com/files/c0x000k09.html" href_cetemp="http://www.163pan.com/files/c0x000k09.html">&lt;本文PDF文档下载&gt;</a><br><br>locale和facet<br><br>C++的locale框架比C更完备。C++除了一个笼统本地策略集locale，还可以为locale指定具体的策略facet，甚至可以用自己定义的facet去改造一个现有的locale产生一个新的locale。如果有一个facet类NewFacet需要添加到某个old_loc中形成新new_loc，需要另外一个构造函数，通常的做法是：<br>std::locale new_loc(old_loc, new NewFacet);<br>标准库里的标准facet都具有自己特有的功能，访问一个locale对象中特定的facet需要使用模板函数use_facet：<br>template &lt;class Facet&gt; const Facet&amp; use_factet(const locale&amp;);<br>换一种说法，use_facet把一个facet类实例化成了对象，由此就可以使用这个facet对象的成员函数。<br><br>codecvt<br><br>codecvt就是一个标准facet。在C++的设计框架里，这是一个通用的代码转换模板——也就是说，并不是仅仅为宽窄转换制定的。<br>templat &lt;class I, class E, class State&gt; class std::codecvt: public locale, public codecvt_base{...};<br>I表示内部编码，E表示外部编码，State是不同转换方式的标识，如果定义如下类型：<br>typedef std::codecvt&lt;wchar_t, char, mbstate_t&gt; CodecvtFacet;<br>那么CodecvtFacet就是一个标准的宽窄转换facet，其中mbstate_t是标准宽窄转换的State。<br><br>内部编码和外部编码<br><br>我们考虑第1节中提到的C++编译器读取源文件时候的情形，当读到L"中文abc"的时候，外部编码，也就是源文件的编码，是GB2312或者UTF-8的char，而编译器必须将其翻译为UCS-2BE或者UTF-32BE的wchar_t，这也就是程序的内部编码。如果不是宽字符串，内外编码都是char，也就不需要转换了。类似的，当C++读写文件的时候 ，就会可能需要到内外编码转换。事实上，codecvt就正是被文件流缓存basic_filebuf所使用的。理解这一点很重要，原因会在下一小节看到。<br><br>CodecvtFacet的in()和out()<br>因为在CodecvtFacet中，内部编码设置为wchar_t，外部编码设置为char，转换模式是标准宽窄转换mbstate_t，所以，类方法in()就是从char标准转换到wchar_t，out()就是从wchar_t标准转换到char。这就成了我们正需要的内外转换函数。<br>result in(State&amp; s, const E* from, const E* from_end, const E*&amp; from_next, I* to,&nbsp; I* to_end, I*&amp; to_next) const;<br>result out(State&amp; s, const I* from, const I* from_end, const I*&amp; from_next, E* to, E* to_end, E*&amp; to_next) const;<br>其中，s是非const引用，保存着转换位移状态信息。这里需要重点强调的是，因为转换的实际工作交给了运行时库，也就是说，转换可能不是在程序的主进程中完成的，而转换工作依赖于查询s的值，因此，如果s在转换结束前析构，就可能抛出运行时异常。所以，最安全的办法是，将s设置为全局变量！<br>const的3个指针分别是待转换字符串的起点，终点，和出现错误时候的停点（的下一个位置）；另外3个指针是转换目标字符串的起点，终点以及出现错误时候的停点（的下一个位置）。<br><br>代码如下：<br>头文件<br>
<div style="BORDER-BOTTOM: #cccccc 1px solid; BORDER-LEFT: #cccccc 1px solid; PADDING-BOTTOM: 4px; BACKGROUND-COLOR: #eeeeee; PADDING-LEFT: 4px; WIDTH: 98%; PADDING-RIGHT: 5px; FONT-SIZE: 13px; WORD-BREAK: break-all; BORDER-TOP: #cccccc 1px solid; BORDER-RIGHT: #cccccc 1px solid; PADDING-TOP: 4px"><span style="COLOR: #008000">//</span><span style="COLOR: #008000">Filename&nbsp;string_wstring_cppcvt.hpp</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"><br>#ifndef&nbsp;STRING_WSTRING_CPPCVT_HPP<br></span><span style="COLOR: #0000ff">#define</span><span style="COLOR: #000000">&nbsp;STRING_WSTRING_CPPCVT_HPP</span><span style="COLOR: #000000"><br><br>#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">iostream</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br>#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><br></span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;std::wstring&nbsp;s2ws(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;std::</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">&nbsp;s);<br></span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;std::</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">&nbsp;ws2s(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;std::wstring</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">&nbsp;s);<br><br></span><span style="COLOR: #0000ff">#endif</span></div>
实现：<br>
<div style="BORDER-BOTTOM: #cccccc 1px solid; BORDER-LEFT: #cccccc 1px solid; PADDING-BOTTOM: 4px; BACKGROUND-COLOR: #eeeeee; PADDING-LEFT: 4px; WIDTH: 98%; PADDING-RIGHT: 5px; FONT-SIZE: 13px; WORD-BREAK: break-all; BORDER-TOP: #cccccc 1px solid; BORDER-RIGHT: #cccccc 1px solid; PADDING-TOP: 4px"><span style="COLOR: #000000">#include&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">string_wstring_cppcvt.hpp</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"><br><br>mbstate_t&nbsp;in_cvt_state;<br>mbstate_t&nbsp;out_cvt_state;<br><br></span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;std::wstring&nbsp;s2ws(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;std::</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">&nbsp;s)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;std::locale&nbsp;sys_loc(</span><span style="COLOR: #000000">""</span><span style="COLOR: #000000">);<br><br>&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">*</span><span style="COLOR: #000000">&nbsp;src_str&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;s.c_str();<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;size_t&nbsp;BUFFER_SIZE&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;s.size()&nbsp;</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;wchar_t</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;intern_buffer&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;wchar_t[BUFFER_SIZE];<br>&nbsp;&nbsp;&nbsp;&nbsp;wmemset(intern_buffer,&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">,&nbsp;BUFFER_SIZE);<br><br>&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">*</span><span style="COLOR: #000000">&nbsp;extern_from&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;src_str;<br>&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">*</span><span style="COLOR: #000000">&nbsp;extern_from_end&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;extern_from&nbsp;</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">&nbsp;s.size();<br>&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">*</span><span style="COLOR: #000000">&nbsp;extern_from_next&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;wchar_t</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;intern_to&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;intern_buffer;<br>&nbsp;&nbsp;&nbsp;&nbsp;wchar_t</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;intern_to_end&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;intern_to&nbsp;</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">&nbsp;BUFFER_SIZE;<br>&nbsp;&nbsp;&nbsp;&nbsp;wchar_t</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;intern_to_next&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;typedef&nbsp;std::codecvt</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">wchar_t,&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">,&nbsp;mbstate_t</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;CodecvtFacet;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;CodecvtFacet::result&nbsp;cvt_rst&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::use_facet</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">CodecvtFacet</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">(sys_loc).</span><span style="COLOR: #0000ff">in</span><span style="COLOR: #000000">(<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;in_cvt_state,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;extern_from,&nbsp;extern_from_end,&nbsp;extern_from_next,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;intern_to,&nbsp;intern_to_end,&nbsp;intern_to_next);<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;(cvt_rst&nbsp;</span><span style="COLOR: #000000">!=</span><span style="COLOR: #000000">&nbsp;CodecvtFacet::ok)&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">switch</span><span style="COLOR: #000000">(cvt_rst)&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">case</span><span style="COLOR: #000000">&nbsp;CodecvtFacet::partial:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::cerr&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">partial</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">break</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">case</span><span style="COLOR: #000000">&nbsp;CodecvtFacet::error:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::cerr&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">error</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">break</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">case</span><span style="COLOR: #000000">&nbsp;CodecvtFacet::noconv:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::cerr&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">noconv</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">break</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">default</span><span style="COLOR: #000000">:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::cerr&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">unknown</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::cerr&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,&nbsp;please&nbsp;check&nbsp;in_cvt_state.</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;std::endl;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;std::wstring&nbsp;result&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;intern_buffer;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;delete&nbsp;[]intern_buffer;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;result;<br>}<br><br></span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;std::</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">&nbsp;ws2s(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;std::wstring</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">&nbsp;ws)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;std::locale&nbsp;sys_loc(</span><span style="COLOR: #000000">""</span><span style="COLOR: #000000">);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;wchar_t</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;src_wstr&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;ws.c_str();<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;size_t&nbsp;MAX_UNICODE_BYTES&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">4</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;size_t&nbsp;BUFFER_SIZE&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ws.size()&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;MAX_UNICODE_BYTES&nbsp;</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;extern_buffer&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">[BUFFER_SIZE];<br>&nbsp;&nbsp;&nbsp;&nbsp;memset(extern_buffer,&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">,&nbsp;BUFFER_SIZE);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;wchar_t</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;intern_from&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;src_wstr;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;wchar_t</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;intern_from_end&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;intern_from&nbsp;</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">&nbsp;ws.size();<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;wchar_t</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;intern_from_next&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;extern_to&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;extern_buffer;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;extern_to_end&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;extern_to&nbsp;</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">&nbsp;BUFFER_SIZE;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;extern_to_next&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;typedef&nbsp;std::codecvt</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">wchar_t,&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">,&nbsp;mbstate_t</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;CodecvtFacet;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;CodecvtFacet::result&nbsp;cvt_rst&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::use_facet</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">CodecvtFacet</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">(sys_loc).</span><span style="COLOR: #0000ff">out</span><span style="COLOR: #000000">(<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;out_cvt_state,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;intern_from,&nbsp;intern_from_end,&nbsp;intern_from_next,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;extern_to,&nbsp;extern_to_end,&nbsp;extern_to_next);<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;(cvt_rst&nbsp;</span><span style="COLOR: #000000">!=</span><span style="COLOR: #000000">&nbsp;CodecvtFacet::ok)&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">switch</span><span style="COLOR: #000000">(cvt_rst)&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">case</span><span style="COLOR: #000000">&nbsp;CodecvtFacet::partial:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::cerr&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">partial</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">break</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">case</span><span style="COLOR: #000000">&nbsp;CodecvtFacet::error:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::cerr&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">error</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">break</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">case</span><span style="COLOR: #000000">&nbsp;CodecvtFacet::noconv:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::cerr&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">noconv</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">break</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">default</span><span style="COLOR: #000000">:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::cerr&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">unknown</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::cerr&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,&nbsp;please&nbsp;check&nbsp;out_cvt_state.</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;std::endl;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;std::</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">&nbsp;result&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;extern_buffer;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;delete&nbsp;[]extern_buffer;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;result;<br>}</span></div>
最后补充说明一下std::use_facet&lt;CodecvtFacet&gt;(sys_loc).in()和std::use_facet&lt;CodecvtFacet&gt;(sys_loc).out()。sys_loc是系统的locale，这个locale中就包含着特定的codecvt facet，我们已经typedef为了CodecvtFacet。用use_facet对CodecvtFacet进行了实例化，所以可以使用这个facet的方法in()和out()。 
<img src ="http://www.cppblog.com/lf426/aggbug/118772.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/lf426/" target="_blank">lf426</a> 2010-06-26 13:39 <a href="http://www.cppblog.com/lf426/archive/2010/06/26/118772.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>彻底解密C++宽字符：3、利用C运行时库函数转换</title><link>http://www.cppblog.com/lf426/archive/2010/06/26/118762.html</link><dc:creator>lf426</dc:creator><author>lf426</author><pubDate>Sat, 26 Jun 2010 03:17:00 GMT</pubDate><guid>http://www.cppblog.com/lf426/archive/2010/06/26/118762.html</guid><wfw:comment>http://www.cppblog.com/lf426/comments/118762.html</wfw:comment><comments>http://www.cppblog.com/lf426/archive/2010/06/26/118762.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/lf426/comments/commentRss/118762.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/lf426/services/trackbacks/118762.html</trackback:ping><description><![CDATA[<a title="<本文pdf文档下载>" href="http://www.163pan.com/files/c0x000k09.html" href_cetemp="http://www.163pan.com/files/c0x000k09.html">&lt;本文PDF文档下载&gt;</a><br><br>std::locale<br><br>通过前面两节的知识，我们知道了在C/C++中，字符（串）和宽字符（串）之间的转换不是简单的，固定的数学关系，宽窄转换依赖于本地化策略集（locale）。换句话说，一个程序在运行之前并不知道系统的本地化策略集是什么，程序只有在运行之后才通过locale获得当时的本地化策略集。<br>C有自己的locale函数，我们这里直接介绍C++的locale类。<br>先讨论locale的构造函数：<br>locale() throw();<br>这个构造函数是获得当前程序的locale，用法如下：<br>std::locale app_loc = std::locale();<br>或者（这是构造对象的两种表示方式，后同）<br>std::locale app_loc;<br>另外一个构造函数是：<br>explicit locale(const char* name);<br>这个构造函数以name的名字创建新的locale。重要的locale对象有：<br>std::locale sys_loc("");&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//获得当前系统环境的locale<br>std::locale C_loc("C");&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;或者&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::locale C_loc = std::locale::classic();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//获得C定义locale<br>std::locale old_loc = std::locale::global(new_loc);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//将new_loc设置为当前全局locale，并将原来的locale返回给old_loc<br>除了这些，其它的name具体名字依赖于C++编译器和操作系统，比如Linux下gcc中文系统的locale名字为"zh_CN.UTF-8"，中文Windows可以用"chs"（更加完整的名字可以用name()函数查看）。<br><br>mbstowcs()和wcstombs()<br><br>这两个C运行时库函数依赖于全局locale进行转换，所以，使用前必须先设置全局locale。<br>std::locale已经包含在&lt;iostream&gt;中了，再加上我们需要用到的C++字符串，所以包含&lt;string&gt;。<br>我们先看窄到宽的转换函数：<br>
<div style="BORDER-BOTTOM: #cccccc 1px solid; BORDER-LEFT: #cccccc 1px solid; PADDING-BOTTOM: 4px; BACKGROUND-COLOR: #eeeeee; PADDING-LEFT: 4px; WIDTH: 98%; PADDING-RIGHT: 5px; FONT-SIZE: 13px; WORD-BREAK: break-all; BORDER-TOP: #cccccc 1px solid; BORDER-RIGHT: #cccccc 1px solid; PADDING-TOP: 4px"><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;std::wstring&nbsp;s2ws(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;std::</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">&nbsp;s)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;std::locale&nbsp;old_loc&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::locale::global(std::locale(</span><span style="COLOR: #000000">""</span><span style="COLOR: #000000">));<br><br>&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">*</span><span style="COLOR: #000000">&nbsp;src_str&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;s.c_str();<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;size_t&nbsp;buffer_size&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;s.size()&nbsp;</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;wchar_t</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;dst_wstr&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;wchar_t[buffer_size];<br>&nbsp;&nbsp;&nbsp;&nbsp;wmemset(dst_wstr,&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">,&nbsp;buffer_size);<br>&nbsp;&nbsp;&nbsp;&nbsp;mbstowcs(dst_wstr,&nbsp;src_str,&nbsp;buffer_size);<br>&nbsp;&nbsp;&nbsp;&nbsp;std::wstring&nbsp;result&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;dst_wstr;<br>&nbsp;&nbsp;&nbsp;&nbsp;delete&nbsp;[]dst_wstr;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;std::locale::global(old_loc);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;result;<br>}</span></div>
我们将全局locale设置为系统locale，并保存原来的全局locale在old_loc中。<br>在制定转换空间缓存大小的时候，考虑如下：char是用1个或多个对象，也就是1个或者多个字节来表示各种符号：比如，GB2312用1个字节表示数字和字母，2个字节表示汉字；UTF-8用一个字节表示数字和字母，3个字节表示汉字，4个字节表示一些很少用到的符号，比如音乐中G大调符号等。wchar_t是用1个对象（2字节或者4字节）来表示各种符号。因此，表示同样的字符串，宽字符串的大小（也就是wchar_t对象的数量）总是小于或者等于窄字符串大小（char对象数量）的。+1是为了在最后预留一个值为0的对象，以便让C风格的char或者wchar_t字符串自动截断——这当然是宽串大小等于窄串大小的时候才会用上的，大部分时候，字符串早在前面某个转换完毕的位置就被0值对象所截断了。<br>最后我们将全局locale设置回原来的old_loc。<br>窄串到宽串的转换函数：<br>
<div style="BORDER-BOTTOM: #cccccc 1px solid; BORDER-LEFT: #cccccc 1px solid; PADDING-BOTTOM: 4px; BACKGROUND-COLOR: #eeeeee; PADDING-LEFT: 4px; WIDTH: 98%; PADDING-RIGHT: 5px; FONT-SIZE: 13px; WORD-BREAK: break-all; BORDER-TOP: #cccccc 1px solid; BORDER-RIGHT: #cccccc 1px solid; PADDING-TOP: 4px"><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;std::</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">&nbsp;ws2s(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;std::wstring</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">&nbsp;ws)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;std::locale&nbsp;old_loc&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::locale::global(std::locale(</span><span style="COLOR: #000000">""</span><span style="COLOR: #000000">));<br><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;wchar_t</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;src_wstr&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;ws.c_str();<br>&nbsp;&nbsp;&nbsp;&nbsp;size_t&nbsp;buffer_size&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;ws.size()&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">4</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;dst_str&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">[buffer_size];<br>&nbsp;&nbsp;&nbsp;&nbsp;memset(dst_str,&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">,&nbsp;buffer_size);<br>&nbsp;&nbsp;&nbsp;&nbsp;wcstombs(dst_str&nbsp;,src_wstr,&nbsp;buffer_size);<br>&nbsp;&nbsp;&nbsp;&nbsp;std::</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">&nbsp;result&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;dst_str;<br>&nbsp;&nbsp;&nbsp;&nbsp;delete&nbsp;[]dst_str;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;std::locale::global(old_loc);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;result;<br>}</span></div>
这里考虑转换空间缓存大小的策略正好相反，在最极端的情况下，所有的wchar_t都需要4个char来表示，所以最大的可能就是4倍加1。<br>这两个函数在VC和gcc中都能正常运行（MinGW因为前面说到的原因不支持宽字符的正常使用），在VC中会给出不安全的警告，这是告诉给那些弄不清宽窄转换实质的人的警告，对于了解到目前这些知识的你我来说，这就是啰嗦了。 
<img src ="http://www.cppblog.com/lf426/aggbug/118762.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/lf426/" target="_blank">lf426</a> 2010-06-26 11:17 <a href="http://www.cppblog.com/lf426/archive/2010/06/26/118762.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>彻底解密C++宽字符：2、Unicode和UTF</title><link>http://www.cppblog.com/lf426/archive/2010/06/25/118739.html</link><dc:creator>lf426</dc:creator><author>lf426</author><pubDate>Fri, 25 Jun 2010 13:51:00 GMT</pubDate><guid>http://www.cppblog.com/lf426/archive/2010/06/25/118739.html</guid><wfw:comment>http://www.cppblog.com/lf426/comments/118739.html</wfw:comment><comments>http://www.cppblog.com/lf426/archive/2010/06/25/118739.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/lf426/comments/commentRss/118739.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/lf426/services/trackbacks/118739.html</trackback:ping><description><![CDATA[<a title="<本文pdf下载>" href="http://www.163pan.com/files/c0x000k09.html" href_cetemp="http://www.163pan.com/files/c0x000k09.html">&lt;本文PDF文档下载&gt;</a><br><br>Unicode和UCS<br><br>Unicode和UCS是两个独立的组织分别制定的一套编码标准，但是因为历史的原因，这两套标准是完全一样的。Unicode这个词用得比较多的原因可能是因为比较容易记住，如果没有特别的声明，在本文所提及的Unicode和UCS就是一个意思。Unicode的目标是建立一套可以包含人类所有语言文字符号你想得到想不到的各种东西的编码，其编码容量甚至预留了火星语以及银河系以外语言的空间——开个玩笑，反正简单的说，Unicode编码集足够的大，如果用计算机单位来表示，其数量比3个字节大一些，不到4个字节。<br><br>Unicode和UTF<br><br>因为Unicode包含的内容太多，其编码在计算机中的表示方法就成为了一个有必要研究的问题。传统编码，比如标准的7位ASCII，在计算机中的表示方法就是占一个字节的后7位，这似乎是不需要解释就符合大家习惯的表示方法。但是当今Unicode的总数达到32位（计算机的最小单位是字节，所以大于3字节，就只能至少用4字节表示），对于大部分常用字符，比如Unicode编码只占一个字节大小的英语字母，占两个字节大小汉字，都用4个字节来储存太奢侈了。另外，如果都用4字节直接表示，就不可避免的出现为0的字节。而我们知道，在C语言中，0x00的字节就是'\0'，表示的是一个字符串（char字符串，非wchar_t）的结束，换句话说，C风格的char字符串无法表示Unicode。<br>因为类似的种种问题，为Unicode在计算机中的编码方法出现了，这就是UTF；所对应的，为UCS编码实现的方式也有自己的说法。一般来说，UTF-x，x表示这套编码一个单位至少占用x位，因为Unicode最长达到32位，所以UTF-x通常是变长的——除了UTF-32；而UCS-y表示一个单位就占用y个字节，所以能表示当今Unicode的UCS-y只有UCS-4，但是因为历史的原因，当Unicode还没那么庞大的时候，2个字节足够表示，所以有UCS-2，现在看来，UCS-2所能表示的Unicode只是当今Unicode的一个子集。<br>也就是说，如果某种编码，能根据一定的规则算法，得到Unicode编码，那么这种编码方式就可以称之为UTF。<br><br>UTF-8和Windows GB2312<br><br>UTF-8是一套&#8220;聪明&#8221;的编码，可能用1，2，3，4个字节表示。通过UTF-8的算法，每一个字节表示的信息都很明确：这是不是某个Unicode编码的第一个字节；如果是第一个字节，这是一个几位Unicode编码。这种&#8220;聪明&#8221;被称为UTF-8的自我同步，也是UTF-8成为网络传输标准编码的原因。<br>另外，UTF-8也不会出现0字节，所以可以表示为char字符串，所以可以成为系统的编码。Linux系统默认使用UTF-8编码。<br>Windows GB2312一般自称为GB2312，其实真正的名字应该是Windows Codepage 936，这也是一种变长的编码：1个字节表示传统的ASCII部分；汉字部分是两个字节的GBK（国标扩（展），拼音声母）。Codepage 936也可以表示为char字符串，是中文Windows系统的默认编码。<br>我们在第1节中看到的<br>const char* s = "中文abc";<br>在Windows中的编码就是Codepage 936；在Linux中的编码就是UTF-8。<br>需要注意的是，Codepage 936不像UTF，跟Unicode没有换算的关系，所以只能通过&#8220;代码页&#8221;技术查表对应。<br><br>UTF-16和UCS-2<br><br>UTF-16用2个字节或者4个字节表示。在2个字节大小的时候，跟UCS-2是一样的。UTF-16不像UTF-8，没有自我同步机制，所以，编码大位在前还是小位在前，就成了见仁见智的问题。我们在第1节中，&#8220;中&#8221;的UCS-2BE（因为是两个字节，所以也就是UTF-16BE）编码是0x4E2D，这里的BE就是大位在后的意思（也就是小位在前了），对应的，如果是UCS-2LE，编码就成了0x2D4E。<br>Windows中的wchar_t就是采用UCS-2BE编码。需要指出的是，C++标准中对wchar_t的要求是要能表示所有系统能识别的字符。Windows自称支持Unicode，但是其wchar_t却不能表示所有的Unicode，由此违背了C++标准。<br><br>UTF-32和UCS-4<br><br>UTF-32在目前阶段等价于UCS-4，都用定长的4个字节表示。UTF-32同样存在BE和LE的问题。Linux的wchar_t编码就是UTF-32BE。在16位以内的时候，UTF-32BE的后两位（前两位是0x00 0x00）等价于UTF-16BE也就等价于UCS-2BE<br><br>BOM<br><br>为了说明一个文件采用的是什么编码，在文件最开始的部分，可以有BOM，比如0xFE 0xFF表示UTF-16BE，0xFF 0xFE 0x00 0x00表示UTF-32LE。UTF-8原本是不需要BOM的，因为其自我同步的特性，但是为了明确说明这是UTF-8（而不是让文本编辑器去猜），也可以加上UTF-8的BOM：0xEF 0xBB 0xBF<br><br>以上内容都讲述得很概略，详细信息请查阅维基百科相关内容。 
<img src ="http://www.cppblog.com/lf426/aggbug/118739.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/lf426/" target="_blank">lf426</a> 2010-06-25 21:51 <a href="http://www.cppblog.com/lf426/archive/2010/06/25/118739.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>彻底解密C++宽字符：1、从char到wchar_t</title><link>http://www.cppblog.com/lf426/archive/2010/06/25/118707.html</link><dc:creator>lf426</dc:creator><author>lf426</author><pubDate>Fri, 25 Jun 2010 06:41:00 GMT</pubDate><guid>http://www.cppblog.com/lf426/archive/2010/06/25/118707.html</guid><wfw:comment>http://www.cppblog.com/lf426/comments/118707.html</wfw:comment><comments>http://www.cppblog.com/lf426/archive/2010/06/25/118707.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/lf426/comments/commentRss/118707.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/lf426/services/trackbacks/118707.html</trackback:ping><description><![CDATA[<a title="<本文pdf文档下载>" href="http://www.163pan.com/files/c0x000k09.html" href_cetemp="http://www.163pan.com/files/c0x000k09.html">&lt;本文PDF文档下载&gt;</a><br><br>&#8220;这个问题比你想象中复杂&#8221;<br>（我也学下BS的风格，虽然这句话是我自己临时想说的。^^）<br><br>从字符到整数<br><br>char是一种整数类型，这句话的含义是，char所能表示的字符在C/C++中都是整数类型。好，接下来，很多文章就会举出一个典型例子，比如，'a'的数值就是0x61。这种说法对吗？如果你细心的读过K&amp;R和BS对于C和C++描述的原著，你就会马上反驳道，0x61只是'a'的ASCII值，并没有任何规定C/C++的char值必须对应ASCII。C/C++甚至没有规定char占几位，只是规定了sizeof(char)等于1。<br>当然，目前大部分情况下，char是8位的，并且，在ASCII范围内的值，与ASCII对应。<br><br>本地化策略集（locale）<br><br>&#8220;将'a'翻译成0x61的整数值&#8221;，&#8220;将ASCII范围内的编码与char的整数值对应起来&#8221;，类似这样的规定，是特定系统和特定编译器制定的，C/C++中有个特定的名词来描述这种规定的集合：本地化策略集（locale。也有翻译成&#8220;现场&#8221;）。而翻译——也就是代码转换（codecvt）只是这个集合中的一个，C++中定义为策略（facet。也有翻译为&#8220;刻面&#8221;）<br><br>C/C++的编译策略<br><br>&#8220;本地化策略集&#8221;是个很好的概念，可惜在字符和字符串这个层面上，C/C++并不使用（C++的locale通常只是影响流（stream）），C/C++使用更直接简单的策略：硬编码。<br>简单的说，字符（串）在程序文件（可执行文件，非源文件）中的表示，与在程序执行中在内存中的表示一致。考虑两种情况：<br>A、char c = 0x61;<br>B、char c = 'a';<br>情况A下，编译器可以直接认识作为整数的c，但是在情况B下，编译器必须将'a'翻译成整数。编译器的策略也很简单，就是直接读取字符（串）在源文件中的编码数值。比如：<br>const char* s = "中文abc";<br>这段字符串在GB2312（Windows 936），也就是我们的windows默认中文系统源文件中的编码为：<br>0xD6&nbsp;&nbsp;&nbsp;0xD0&nbsp;&nbsp;&nbsp;0xCE 0xC4 0x61 0x62 0x63<br>在UTF-8，也就是Linux默认系统源文件中的编码为：<br>0xE4&nbsp;&nbsp;&nbsp;0xB8&nbsp;&nbsp;&nbsp;0xAD&nbsp;&nbsp;&nbsp;0xE6&nbsp;&nbsp;&nbsp;0x96&nbsp;&nbsp;&nbsp;0x87&nbsp;&nbsp;&nbsp;0x61&nbsp;&nbsp;&nbsp;0x62&nbsp;&nbsp;&nbsp;0x63<br>一般情况下，编译器会忠实于源文件的编码为s赋值，例外的情况比如VC会自作聪明的把大部分其他类型编码的字符串转换成GB2312（除了像UTF-8 without signature这样的幸存者）。<br>程序在执行的时候，s也就保持是这样的编码，不会再做其他的转换。<br><br>宽字符 wchar_t<br>正如char没有规定大小，wchar_t同样没有标准限定，标准只是要求一个wchar_t可以表示任何系统所能认识的字符，在win32中，wchar_t为16位；Linux中是32位。wchar_t同样没有规定编码，因为Unicode的概念我们后面才解释，所以这里只是提一下，在win32中，wchar_t的编码是UCS-2BE；而Linux中是UTF-32BE（等价于UCS-4BE），不过简单的说，在16位以内，一个字符的这3种编码值是一样的。因此：<br>const wchar_t* ws = L"中文abc";<br>的编码分别为：<br>0x4E2D&nbsp;&nbsp;&nbsp;0x6587&nbsp;&nbsp;&nbsp;&nbsp;0x0061&nbsp;&nbsp;&nbsp;0x0062&nbsp;&nbsp;&nbsp;0x0063&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//win32，16位<br>0x00004E2D&nbsp;&nbsp;&nbsp;0x00006587&nbsp;&nbsp;&nbsp;&nbsp;0x00000061&nbsp;&nbsp;&nbsp;0x00000062&nbsp;&nbsp;&nbsp;0x00000063&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//Linux，32位<br>大写的L是告诉编译器：这是宽字符串。所以，这时候是需要编译器根据locale来进行翻译的。<br>比如，在Windows环境中，编译器的翻译策略是GB2312到UCS-2BE；Linux环境中的策略是UTF-8到UTF-32BE。<br>这时候就要求源文件的编码与编译器的本地化策略集中代码翻译的策略一致，例如VC只能读取GB2312的源代码（这里还是例外，VC太自作聪明了 ，会将很多其他代码在编译时自动转换成GB2312），而gcc只能读取UTF-8的源代码（这里就有个尴尬，MinGW运行win32下，所以只有GB2312系统才认；而MinGW却用gcc编写，所以自己只认UTF-8，所以结果就是，MinGW的宽字符被废掉了）。<br>宽字符（串）由编译器翻译，还是被硬编码进程序文件中。 
<img src ="http://www.cppblog.com/lf426/aggbug/118707.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/lf426/" target="_blank">lf426</a> 2010-06-25 14:41 <a href="http://www.cppblog.com/lf426/archive/2010/06/25/118707.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>迭代器（iterator）“擦”（erase）出的错误</title><link>http://www.cppblog.com/lf426/archive/2010/06/10/117545.html</link><dc:creator>lf426</dc:creator><author>lf426</author><pubDate>Thu, 10 Jun 2010 03:03:00 GMT</pubDate><guid>http://www.cppblog.com/lf426/archive/2010/06/10/117545.html</guid><wfw:comment>http://www.cppblog.com/lf426/comments/117545.html</wfw:comment><comments>http://www.cppblog.com/lf426/archive/2010/06/10/117545.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/lf426/comments/commentRss/117545.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/lf426/services/trackbacks/117545.html</trackback:ping><description><![CDATA[<p>设计一段演示程序：打印n个数字，然后指定擦掉其中的某一个，重新打印剩下的数字。</p>
<div style="BORDER-BOTTOM: #cccccc 1px solid; BORDER-LEFT: #cccccc 1px solid; PADDING-BOTTOM: 4px; BACKGROUND-COLOR: #eeeeee; PADDING-LEFT: 4px; WIDTH: 98%; PADDING-RIGHT: 5px; FONT-SIZE: 13px; WORD-BREAK: break-all; BORDER-TOP: #cccccc 1px solid; BORDER-RIGHT: #cccccc 1px solid; PADDING-TOP: 4px"><span style="COLOR: #000000">#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">iostream</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br>#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">vector</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><br></span><span style="COLOR: #0000ff">using</span><span style="COLOR: #000000">&nbsp;std::cout;<br></span><span style="COLOR: #0000ff">using</span><span style="COLOR: #000000">&nbsp;std::cin;<br></span><span style="COLOR: #0000ff">using</span><span style="COLOR: #000000">&nbsp;std::endl;<br></span><span style="COLOR: #0000ff">using</span><span style="COLOR: #000000">&nbsp;std::vector;<br><br></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;main(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;argc,&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;argv[])<br>{<br>&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;MAX&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">10</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;vector</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;v;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000">&nbsp;(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;i&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;&nbsp;i&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">&nbsp;MAX;&nbsp;i</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">)&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;v.push_back(i);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cout&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;v[i]&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">'</span><span style="COLOR: #000000">\t</span><span style="COLOR: #000000">'</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;ers&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">while</span><span style="COLOR: #000000">&nbsp;(&nbsp;ers&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">||</span><span style="COLOR: #000000">&nbsp;ers&nbsp;</span><span style="COLOR: #000000">&gt;=</span><span style="COLOR: #000000">&nbsp;MAX)&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cout&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Erase&nbsp;No.</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cin&nbsp;</span><span style="COLOR: #000000">&gt;&gt;</span><span style="COLOR: #000000">&nbsp;ers;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000">&nbsp;(vector</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">::const_iterator&nbsp;i&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;v.begin();&nbsp;i&nbsp;</span><span style="COLOR: #000000">!=</span><span style="COLOR: #000000">&nbsp;v.end();&nbsp;i</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">)&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;(</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">i&nbsp;</span><span style="COLOR: #000000">==</span><span style="COLOR: #000000">&nbsp;ers)&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;v.erase(i);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000">&nbsp;(vector</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">::const_iterator&nbsp;i&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;v.begin();&nbsp;i&nbsp;</span><span style="COLOR: #000000">!=</span><span style="COLOR: #000000">&nbsp;v.end();&nbsp;i</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">)&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cout&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">i&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">'</span><span style="COLOR: #000000">\t</span><span style="COLOR: #000000">'</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;cout&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;endl;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br>}</span></div>
这个程序看似没什么错误，可以顺利编译，也可以顺利运行，甚至，大部分情况下可可以正常完成。<br>我们这里设置的n为10（MAX），事实上，我们擦掉0到8都没有问题，但是，我们要擦掉9的时候，程序却出错了！<br>在我们遍历查找对等值的循环中，一开始v.end()指向第10个元素（数值为9）的后面一个位置（不存在的第11个元素的位置）。当迭代器指向第10个元素（数值为9）的时候，v.erase()生效运行；下一轮循环中，迭代器本来应该指向第11个元素的位置，并且等于v.end()并结束循环。但是，因为我们擦掉了vector中的一个元素，v.end()指向的是现在的最后一个元素——第9个元素的后面，也就是第10个元素的位置。这样，迭代器到了11，而判断确是其是否到10，这将永远无法实现，形成了一个逻辑bug，所以系统抛出错误了。<br>一个修正的办法是把需要擦掉的迭代器找出来，在循环结束后再擦掉，下面修改后的程序就可以正常的擦掉9了。<br>
<div style="BORDER-BOTTOM: #cccccc 1px solid; BORDER-LEFT: #cccccc 1px solid; PADDING-BOTTOM: 4px; BACKGROUND-COLOR: #eeeeee; PADDING-LEFT: 4px; WIDTH: 98%; PADDING-RIGHT: 5px; FONT-SIZE: 13px; WORD-BREAK: break-all; BORDER-TOP: #cccccc 1px solid; BORDER-RIGHT: #cccccc 1px solid; PADDING-TOP: 4px"><span style="COLOR: #000000">#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">iostream</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br>#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">vector</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><br></span><span style="COLOR: #0000ff">using</span><span style="COLOR: #000000">&nbsp;std::cout;<br></span><span style="COLOR: #0000ff">using</span><span style="COLOR: #000000">&nbsp;std::cin;<br></span><span style="COLOR: #0000ff">using</span><span style="COLOR: #000000">&nbsp;std::endl;<br></span><span style="COLOR: #0000ff">using</span><span style="COLOR: #000000">&nbsp;std::vector;<br><br></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;main(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;argc,&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;argv[])<br>{<br>&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;MAX&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">10</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;vector</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;v;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000">&nbsp;(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;i&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;&nbsp;i&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">&nbsp;MAX;&nbsp;i</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">)&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;v.push_back(i);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cout&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;v[i]&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">'</span><span style="COLOR: #000000">\t</span><span style="COLOR: #000000">'</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;ers&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">while</span><span style="COLOR: #000000">&nbsp;(&nbsp;ers&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">||</span><span style="COLOR: #000000">&nbsp;ers&nbsp;</span><span style="COLOR: #000000">&gt;=</span><span style="COLOR: #000000">&nbsp;MAX)&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cout&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Erase&nbsp;No.</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cin&nbsp;</span><span style="COLOR: #000000">&gt;&gt;</span><span style="COLOR: #000000">&nbsp;ers;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;vector</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">::const_iterator&nbsp;ers_i;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000">&nbsp;(vector</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">::const_iterator&nbsp;i&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;v.begin();&nbsp;i&nbsp;</span><span style="COLOR: #000000">!=</span><span style="COLOR: #000000">&nbsp;v.end();&nbsp;i</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">)&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;(</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">i&nbsp;</span><span style="COLOR: #000000">==</span><span style="COLOR: #000000">&nbsp;ers)&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ers_i&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;i;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;v.erase(ers_i);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000">&nbsp;(vector</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">::const_iterator&nbsp;i&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;v.begin();&nbsp;i&nbsp;</span><span style="COLOR: #000000">!=</span><span style="COLOR: #000000">&nbsp;v.end();&nbsp;i</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">)&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cout&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">i&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">'</span><span style="COLOR: #000000">\t</span><span style="COLOR: #000000">'</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;cout&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;endl;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br>}</span></div>
<img src ="http://www.cppblog.com/lf426/aggbug/117545.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/lf426/" target="_blank">lf426</a> 2010-06-10 11:03 <a href="http://www.cppblog.com/lf426/archive/2010/06/10/117545.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>用对象的成员函数引出线程，还是在线程中创建对象？</title><link>http://www.cppblog.com/lf426/archive/2010/06/05/117242.html</link><dc:creator>lf426</dc:creator><author>lf426</author><pubDate>Sat, 05 Jun 2010 13:06:00 GMT</pubDate><guid>http://www.cppblog.com/lf426/archive/2010/06/05/117242.html</guid><wfw:comment>http://www.cppblog.com/lf426/comments/117242.html</wfw:comment><comments>http://www.cppblog.com/lf426/archive/2010/06/05/117242.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/lf426/comments/commentRss/117242.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/lf426/services/trackbacks/117242.html</trackback:ping><description><![CDATA[还是先看一段非多线程的程序。我们用TestClass1表示在线程中创建的对象类，用TestClass2表示与创建线程的操作在同一定义域（也就是同一对{}之中的）的局部变量的对象类。<br>之所以提出TestClass2这种类，是因为在实际编程中我们会遇到这种情况：我们不可预知这个类何时创建以及创建多少；这个类的对象是一个新线程的参数。比如，在sokcet中的TCP server端就会有这种情况：如果每一个新连接的client都用创建一个新的线程去处理，我们不可预知在什么时候会有多少客户端连过来。<br>我们先观察没有多线程的时候对象的生命周期：<br>
<div style="BORDER-BOTTOM: #cccccc 1px solid; BORDER-LEFT: #cccccc 1px solid; PADDING-BOTTOM: 4px; BACKGROUND-COLOR: #eeeeee; PADDING-LEFT: 4px; WIDTH: 98%; PADDING-RIGHT: 5px; FONT-SIZE: 13px; WORD-BREAK: break-all; BORDER-TOP: #cccccc 1px solid; BORDER-RIGHT: #cccccc 1px solid; PADDING-TOP: 4px"><span style="COLOR: #000000">#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">iostream</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br>#include&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">windows.h</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"><br><br></span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;TestClass1{<br></span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000">:<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;x;<br></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">explicit</span><span style="COLOR: #000000">&nbsp;TestClass1(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;to_x):x(to_x)<br>&nbsp;&nbsp;&nbsp;&nbsp;{}<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">~</span><span style="COLOR: #000000">TestClass1()<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::cerr&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">destruction:&nbsp;1.</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;std::endl;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;show()&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::cerr&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;x&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;std::endl;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>};<br><br></span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;TestClass2{<br></span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000">:<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;pX;<br></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">explicit</span><span style="COLOR: #000000">&nbsp;TestClass2(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;to_x)<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pX&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">pX&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;to_x;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">~</span><span style="COLOR: #000000">TestClass2()<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;delete&nbsp;pX;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::cerr&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">destruction:&nbsp;2.</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;std::endl;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&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;value()&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">pX;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>};<br><br>DWORD&nbsp;WINAPI&nbsp;thread_func(LPVOID&nbsp;pN)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;Sleep(</span><span style="COLOR: #000000">200</span><span style="COLOR: #000000">);<br>&nbsp;&nbsp;&nbsp;&nbsp;TestClass1&nbsp;test((</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">((TestClass2</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">)pN)).value());<br>&nbsp;&nbsp;&nbsp;&nbsp;test.show();<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br>}<br><br></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;main(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;argc,&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;argv[])<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000">&nbsp;(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;i&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;&nbsp;i&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">3</span><span style="COLOR: #000000">;&nbsp;</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">i)&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TestClass2&nbsp;n(</span><span style="COLOR: #000000">5</span><span style="COLOR: #000000">);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;thread_func((LPVOID)</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">n);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::cerr&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">loop:&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;i</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;std::endl;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;Sleep(</span><span style="COLOR: #000000">2000</span><span style="COLOR: #000000">);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;std::cout&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">main()&nbsp;ok.</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;std::endl;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br>}</span></div>
这是标准的C++模式，对象的生命周期是可以预见的：<br>
<div style="BORDER-BOTTOM: #cccccc 1px solid; BORDER-LEFT: #cccccc 1px solid; PADDING-BOTTOM: 4px; BACKGROUND-COLOR: #eeeeee; PADDING-LEFT: 4px; WIDTH: 98%; PADDING-RIGHT: 5px; FONT-SIZE: 13px; WORD-BREAK: break-all; BORDER-TOP: #cccccc 1px solid; BORDER-RIGHT: #cccccc 1px solid; PADDING-TOP: 4px"><span style="COLOR: #000000">5</span><span style="COLOR: #000000"><br>destruction:&nbsp;</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">.<br>loop:&nbsp;</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000"><br>destruction:&nbsp;</span><span style="COLOR: #000000">2</span><span style="COLOR: #000000">.<br></span><span style="COLOR: #000000">5</span><span style="COLOR: #000000"><br>destruction:&nbsp;</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">.<br>loop:&nbsp;</span><span style="COLOR: #000000">2</span><span style="COLOR: #000000"><br>destruction:&nbsp;</span><span style="COLOR: #000000">2</span><span style="COLOR: #000000">.<br></span><span style="COLOR: #000000">5</span><span style="COLOR: #000000"><br>destruction:&nbsp;</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">.<br>loop:&nbsp;</span><span style="COLOR: #000000">3</span><span style="COLOR: #000000"><br>destruction:&nbsp;</span><span style="COLOR: #000000">2</span><span style="COLOR: #000000">.<br>main()&nbsp;ok.<br>请按任意键继续.&nbsp;.&nbsp;.</span></div>
如果我们改成线程调用：<br>
<div style="BORDER-BOTTOM: #cccccc 1px solid; BORDER-LEFT: #cccccc 1px solid; PADDING-BOTTOM: 4px; BACKGROUND-COLOR: #eeeeee; PADDING-LEFT: 4px; WIDTH: 98%; PADDING-RIGHT: 5px; FONT-SIZE: 13px; WORD-BREAK: break-all; BORDER-TOP: #cccccc 1px solid; BORDER-RIGHT: #cccccc 1px solid; PADDING-TOP: 4px"><span style="COLOR: #000000">#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">iostream</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br>#include&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">windows.h</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"><br><br></span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;TestClass1{<br></span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000">:<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;x;<br></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">explicit</span><span style="COLOR: #000000">&nbsp;TestClass1(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;to_x):x(to_x)<br>&nbsp;&nbsp;&nbsp;&nbsp;{}<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">~</span><span style="COLOR: #000000">TestClass1()<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::cerr&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">destruction:&nbsp;1.</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;std::endl;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;show()&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::cerr&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;x&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;std::endl;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>};<br><br></span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;TestClass2{<br></span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000">:<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;pX;<br></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">explicit</span><span style="COLOR: #000000">&nbsp;TestClass2(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;to_x)<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pX&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">pX&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;to_x;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">~</span><span style="COLOR: #000000">TestClass2()<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;delete&nbsp;pX;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::cerr&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">destruction:&nbsp;2.</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;std::endl;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&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;value()&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">pX;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>};<br><br>DWORD&nbsp;WINAPI&nbsp;thread_func(LPVOID&nbsp;pN)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;Sleep(</span><span style="COLOR: #000000">200</span><span style="COLOR: #000000">);<br>&nbsp;&nbsp;&nbsp;&nbsp;TestClass1&nbsp;test((</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">((TestClass2</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">)pN)).value());<br>&nbsp;&nbsp;&nbsp;&nbsp;test.show();<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br>}<br><br></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;main(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;argc,&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;argv[])<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000">&nbsp;(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;i&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;&nbsp;i&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">3</span><span style="COLOR: #000000">;&nbsp;</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">i)&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TestClass2&nbsp;n(</span><span style="COLOR: #000000">5</span><span style="COLOR: #000000">);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HANDLE&nbsp;hThrd;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DWORD&nbsp;thrdId;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;hThrd&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;CreateThread(&nbsp;&nbsp;&nbsp;&nbsp;NULL,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;thread_func,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(LPVOID)</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">n,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">thrdId);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::cerr&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">loop:&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;i</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;std::endl;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;Sleep(</span><span style="COLOR: #000000">2000</span><span style="COLOR: #000000">);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;std::cout&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">main()&nbsp;ok.</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;std::endl;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br>}<br></span></div>
可以看到函数返回了错误的值（至于为什么每次都是36我还不清楚，但是至少不是正确的数字5），这是因为在线程调用TestClass2的对象之前已经被析构的缘故。<br>
<div style="BORDER-BOTTOM: #cccccc 1px solid; BORDER-LEFT: #cccccc 1px solid; PADDING-BOTTOM: 4px; BACKGROUND-COLOR: #eeeeee; PADDING-LEFT: 4px; WIDTH: 98%; PADDING-RIGHT: 5px; FONT-SIZE: 13px; WORD-BREAK: break-all; BORDER-TOP: #cccccc 1px solid; BORDER-RIGHT: #cccccc 1px solid; PADDING-TOP: 4px"><span style="COLOR: #000000">loop:&nbsp;</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000"><br>destruction:&nbsp;</span><span style="COLOR: #000000">2</span><span style="COLOR: #000000">.<br>loop:&nbsp;</span><span style="COLOR: #000000">2</span><span style="COLOR: #000000"><br>destruction:&nbsp;</span><span style="COLOR: #000000">2</span><span style="COLOR: #000000">.<br>loop:&nbsp;</span><span style="COLOR: #000000">3</span><span style="COLOR: #000000"><br>destruction:&nbsp;</span><span style="COLOR: #000000">2</span><span style="COLOR: #000000">.<br></span><span style="COLOR: #000000">36</span><span style="COLOR: #000000"><br>destruction:&nbsp;</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">.<br></span><span style="COLOR: #000000">36</span><span style="COLOR: #000000"><br>destruction:&nbsp;</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">.<br></span><span style="COLOR: #000000">36</span><span style="COLOR: #000000"><br>destruction:&nbsp;</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">.<br>main()&nbsp;ok.<br>请按任意键继续.&nbsp;.&nbsp;.</span></div>
所以，如果我们设想构造一个类，这个类的对象可以调用包含this的线程，那么这个对象一定不能是局部变量，或者说，我们必须在循环的{}对之前先把这些对象构造出来。这与我们的需求不符合——我们并不知道需要多少对象以及如何构造（比如构造TCP的通讯socket需要accept()接受客户端的信息），在这种情况下，我们只能在线程中去构造对象，这样的对象生命周期跟线程函数一样。<br>或者说，如果我们希望用类来封装线程，那么这些可以调用线程的对象必须是全局的。相关内容请参考本人前面的教程&#8220;初试多线程&#8221;等。 
<img src ="http://www.cppblog.com/lf426/aggbug/117242.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/lf426/" target="_blank">lf426</a> 2010-06-05 21:06 <a href="http://www.cppblog.com/lf426/archive/2010/06/05/117242.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>在多线程中抛出的异常出错？</title><link>http://www.cppblog.com/lf426/archive/2010/06/05/117241.html</link><dc:creator>lf426</dc:creator><author>lf426</author><pubDate>Sat, 05 Jun 2010 12:16:00 GMT</pubDate><guid>http://www.cppblog.com/lf426/archive/2010/06/05/117241.html</guid><wfw:comment>http://www.cppblog.com/lf426/comments/117241.html</wfw:comment><comments>http://www.cppblog.com/lf426/archive/2010/06/05/117241.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/lf426/comments/commentRss/117241.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/lf426/services/trackbacks/117241.html</trackback:ping><description><![CDATA[以下以win32平台为例。我们先看一个非多线程的程序：<br>
<div style="BORDER-BOTTOM: #cccccc 1px solid; BORDER-LEFT: #cccccc 1px solid; PADDING-BOTTOM: 4px; BACKGROUND-COLOR: #eeeeee; PADDING-LEFT: 4px; WIDTH: 98%; PADDING-RIGHT: 5px; FONT-SIZE: 13px; WORD-BREAK: break-all; BORDER-TOP: #cccccc 1px solid; BORDER-RIGHT: #cccccc 1px solid; PADDING-TOP: 4px"><span style="COLOR: #000000">#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">iostream</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br>#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">windows.h</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><br>DWORD&nbsp;WINAPI&nbsp;thread_func(LPVOID&nbsp;pN)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000">&nbsp;(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;i&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;&nbsp;i&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">((</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">)pN);&nbsp;</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">i)&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::cout&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;i</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">\t</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;std::cout&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;std::endl;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">throw</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">ok.</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;std::cout&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">thread_func()&nbsp;done.</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;std::endl;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br>}<br><br></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;main(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;argc,&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;argv[])<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;n&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">5</span><span style="COLOR: #000000">;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">try</span><span style="COLOR: #000000">{<br>&nbsp;&nbsp;&nbsp;&nbsp;thread_func((LPVOID)</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">n);<br>&nbsp;&nbsp;&nbsp;&nbsp;Sleep(</span><span style="COLOR: #000000">2000</span><span style="COLOR: #000000">);<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">catch</span><span style="COLOR: #000000">&nbsp;(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;s)&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::cerr&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;s&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;std::endl;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit(</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">);<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;std::cout&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">main()&nbsp;done.</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;std::endl;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br>}</span></div>
可以看到，函数thread_func()可以正确的抛出异常并被main()的catch捕捉。但是，如果用一个新线程来运行thread_func()会出现什么情况呢？<br>
<div style="BORDER-BOTTOM: #cccccc 1px solid; BORDER-LEFT: #cccccc 1px solid; PADDING-BOTTOM: 4px; BACKGROUND-COLOR: #eeeeee; PADDING-LEFT: 4px; WIDTH: 98%; PADDING-RIGHT: 5px; FONT-SIZE: 13px; WORD-BREAK: break-all; BORDER-TOP: #cccccc 1px solid; BORDER-RIGHT: #cccccc 1px solid; PADDING-TOP: 4px"><span style="COLOR: #000000">#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">iostream</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br>#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">windows.h</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><br>DWORD&nbsp;WINAPI&nbsp;thread_func(LPVOID&nbsp;pN)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000">&nbsp;(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;i&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;&nbsp;i&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">((</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">)pN);&nbsp;</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">i)&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::cout&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;i</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">\t</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;std::cout&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;std::endl;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">throw</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">ok.</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;std::cout&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">thread_func()&nbsp;done.</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;std::endl;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br>}<br><br></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;main(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;argc,&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;argv[])<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;HANDLE&nbsp;hThrd;<br>&nbsp;&nbsp;&nbsp;&nbsp;DWORD&nbsp;thrdId;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;n&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">5</span><span style="COLOR: #000000">;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">try</span><span style="COLOR: #000000">{<br>&nbsp;&nbsp;&nbsp;&nbsp;hThrd&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;CreateThread(&nbsp;&nbsp;&nbsp;&nbsp;NULL,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;thread_func,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(LPVOID)</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">n,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">thrdId);<br>&nbsp;&nbsp;&nbsp;&nbsp;Sleep(</span><span style="COLOR: #000000">2000</span><span style="COLOR: #000000">);<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">catch</span><span style="COLOR: #000000">&nbsp;(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;s)&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::cerr&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;s&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;std::endl;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit(</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">);<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;std::cout&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">main()&nbsp;done.</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;std::endl;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br>}</span></div>
很不幸，这个程序编译的时候是可以通过的，但是运行时出错：<br>
<div style="BORDER-BOTTOM: #cccccc 1px solid; BORDER-LEFT: #cccccc 1px solid; PADDING-BOTTOM: 4px; BACKGROUND-COLOR: #eeeeee; PADDING-LEFT: 4px; WIDTH: 98%; PADDING-RIGHT: 5px; FONT-SIZE: 13px; WORD-BREAK: break-all; BORDER-TOP: #cccccc 1px solid; BORDER-RIGHT: #cccccc 1px solid; PADDING-TOP: 4px"><span style="COLOR: #000000">1</span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">2</span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">3</span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">4</span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">5</span><span style="COLOR: #000000"><br><br>This&nbsp;application&nbsp;has&nbsp;requested&nbsp;the&nbsp;Runtime&nbsp;to&nbsp;terminate&nbsp;it&nbsp;</span><span style="COLOR: #0000ff">in</span><span style="COLOR: #000000">&nbsp;an&nbsp;unusual&nbsp;way.<br>Please&nbsp;contact&nbsp;the&nbsp;application</span><span style="COLOR: #000000">'</span><span style="COLOR: #000000">s&nbsp;support&nbsp;team&nbsp;for&nbsp;more&nbsp;information.</span><span style="COLOR: #000000"><br></span><span style="COLOR: #000000">请按任意键继续.&nbsp;.&nbsp;.</span></div>
而且同时会有一个运行时错误的提示。事实上，这个错误提示意味着程序在没有发现try{}的时候看到了throw。<br>通过试验，我发现系统（这里是win32）不能将CreateThread()所产生的线程归结到try{}中。更加严重的情况是，即使用一个函数囊括了整个程序，然后try这个函数，其他线程依然脱离了这个try。<br>所以，一个解决方法是，凡是遇到新的线程，必须在新线程中重新写异常处理。不然，就如google代码标准里所说的那样，不使用C++的异常机制。毕竟C++没有定义多线程的标准，所以也就无从说起多线程中异常处理的标准。<br>最后附上在新线程写异常处理的参考：<br>
<div style="BORDER-BOTTOM: #cccccc 1px solid; BORDER-LEFT: #cccccc 1px solid; PADDING-BOTTOM: 4px; BACKGROUND-COLOR: #eeeeee; PADDING-LEFT: 4px; WIDTH: 98%; PADDING-RIGHT: 5px; FONT-SIZE: 13px; WORD-BREAK: break-all; BORDER-TOP: #cccccc 1px solid; BORDER-RIGHT: #cccccc 1px solid; PADDING-TOP: 4px"><span style="COLOR: #000000">#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">iostream</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br>#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">windows.h</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><br>DWORD&nbsp;WINAPI&nbsp;thread_func(LPVOID&nbsp;pN)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">try</span><span style="COLOR: #000000">{<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000">&nbsp;(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;i&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;&nbsp;i&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">((</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">)pN);&nbsp;</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">i)&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::cout&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;i</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">\t</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;std::cout&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;std::endl;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">throw</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">ok.</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">catch</span><span style="COLOR: #000000">&nbsp;(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;s)&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::cerr&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;s&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;std::endl;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit(</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">);<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;std::cout&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">thread_func()&nbsp;done.</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;std::endl;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br>}<br><br></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;main(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;argc,&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;argv[])<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;HANDLE&nbsp;hThrd;<br>&nbsp;&nbsp;&nbsp;&nbsp;DWORD&nbsp;thrdId;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;n&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">5</span><span style="COLOR: #000000">;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;hThrd&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;CreateThread(&nbsp;&nbsp;&nbsp;&nbsp;NULL,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;thread_func,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(LPVOID)</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">n,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">thrdId);<br>&nbsp;&nbsp;&nbsp;&nbsp;Sleep(</span><span style="COLOR: #000000">2000</span><span style="COLOR: #000000">);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;std::cout&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">main()&nbsp;done.</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;std::endl;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br>}</span></div>
<img src ="http://www.cppblog.com/lf426/aggbug/117241.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/lf426/" target="_blank">lf426</a> 2010-06-05 20:16 <a href="http://www.cppblog.com/lf426/archive/2010/06/05/117241.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>函数指针与成员函数指针</title><link>http://www.cppblog.com/lf426/archive/2008/04/26/48182.html</link><dc:creator>lf426</dc:creator><author>lf426</author><pubDate>Sat, 26 Apr 2008 04:39:00 GMT</pubDate><guid>http://www.cppblog.com/lf426/archive/2008/04/26/48182.html</guid><wfw:comment>http://www.cppblog.com/lf426/comments/48182.html</wfw:comment><comments>http://www.cppblog.com/lf426/archive/2008/04/26/48182.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/lf426/comments/commentRss/48182.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/lf426/services/trackbacks/48182.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 游戏的设计离不开多线程，在C++新标准出来之前，多线程的设计还是多以依赖特定系统的函数库或者某些特定的函数库为主，如同SDL，打开多线程的函数也主要是C函数。我们当然很期待boost中真正意义上的C++多线程类的加入，不过仍然需要等待。问题就出在打开多线程的C函数上，因为他们通常调用的是函数指针，但是在C++中，我们通常把函数绑定到了与其数据相关的类中，也就是说，我们在C++中很少用到&#8220;单身&#8221;的函数，成员函数可以被那些调用函数指针的启动多线程的函数调用吗？<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 答案是：通常不行，但是静态成员函数例外。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在C++中，函数指针与成员函数指针完全是两个概念，并且相互之间在任何情况下，无法转换！<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 我们来看这么一个类：<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"><span style="COLOR: #000000">#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">iostream</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><br></span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;A<br>{<br></span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000">:<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;a;<br></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br>&nbsp;&nbsp;&nbsp;&nbsp;A(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;_a):&nbsp;a(_a)<br>&nbsp;&nbsp;&nbsp;&nbsp;{}<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;f1()&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::cout&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">call&nbsp;f1,&nbsp;a&nbsp;=&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;a&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;std::endl;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;f2()&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::cout&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">call&nbsp;f2,&nbsp;a&nbsp;=&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;a&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;std::endl;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;f3(</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;_a)<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::cout&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">call&nbsp;f3,&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_a.f1();<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;friend&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;f4(</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;_a)<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::cout&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">call&nbsp;f4,&nbsp;a&nbsp;=&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;_a.a&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;std::endl;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>};</span></div>
其中函数A::f1()和A::f2()是毫无疑问的成员函数；A::f3()也是成员函数，但是他是静态成员函数；f4()是A类的友元函数，他实际上就是一个普通的函数。<br>A::f1()的指针我们需要这样定义：<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"><span style="COLOR: #000000">typedef&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;(A::</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">pcf)()</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">;</span></div>
作为参数的时候必须这样写&#8220;&amp;A::f1&#8221;。<br>A::f2()的指针我们这样定义：<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"><span style="COLOR: #000000">typedef&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;(A::</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">ptf)()</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">;</span></div>
尽管A::f2()与A::f1()的返回类型不同，但是他们的形参列表是一样的，所以，指针可以通过强制转换进行转换。<br>如果他们的形参列表不一致，则强制转换在编译期间没有问题，但是运行时会抛出异常。<br>这是因为形参列表不一样意味着强制转换后，某些函数无法得到某些必须的参数。所以，这种转换应该是需要避免的。<br>A::f3()和f4()尽管一个是静态成员函数，一个是普通函数，但是他们的指针定义却是一样的：<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"><span style="COLOR: #000000">typedef&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;(</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">pf)(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;A</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">);</span></div>
这也就是为什么调用函数指针的函数可以直接调用静态成员函数指针的原因。<br>作为参数的时候，他们既可以加上&#8220;&amp;&#8221;来写：&#8220;&amp;A::f3&#8221;, &#8220;&amp;f4&#8221;；<br>也可以不用&#8220;&amp;&#8221;：&#8220;A::f3&#8221;, &#8220;f4&#8221;。<br>这是在A类定义域外的情况。在A定义域内，比如在写A的成员函数的时候，静态成员函数甚至可以不需要加上A的定义域符号&#8220;A::&#8221;，直接可以使用&#8220;&amp;f3&#8221;或者&#8220;f3&#8221;。<br>&nbsp;<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"><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;call_A(pcf&nbsp;pF,&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;_a)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;(_a.</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">pF)();<br>}<br><br></span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;call_A(pf&nbsp;pF,&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;_a)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;(</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">pF)(_a);<br>}<br><br></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;main(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;argc,&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;argv[])<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;A&nbsp;a(</span><span style="COLOR: #000000">10</span><span style="COLOR: #000000">);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;call_A(</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">A::f1,&nbsp;a);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;ptf&nbsp;__f2&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">A::f2;<br>&nbsp;&nbsp;&nbsp;&nbsp;pcf&nbsp;_f2&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;(pcf)(__f2);<br>&nbsp;&nbsp;&nbsp;&nbsp;call_A(_f2,&nbsp;a);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;call_A(A::f3,&nbsp;a);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;call_A(f4,&nbsp;a);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br>}</span></div>
可以看到的情况是：<br>1、成员函数的指针与对象是不绑定的。也就是说，尽管我也很希望如果a是A的对象，a.f1()的指针要是能表示成a.f1（或者&#8220;&amp;(a.f1)&#8221;）多好？但是这是不允许的，至少现在是不允许的。我们要调用A::f1()方法，还得指定其对象，所以，这实际上与调用静态成员函数与普通函数是一样的。<br>2、静态成员函数可以代替普通函数被调用函数指针（非成员函数指针）的函数调用。但是静态成员函数有一个好处，就是可以被类私有保护起来——当然，最好是有其他公共成员将其作用对外连接起来的时候。
<img src ="http://www.cppblog.com/lf426/aggbug/48182.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/lf426/" target="_blank">lf426</a> 2008-04-26 12:39 <a href="http://www.cppblog.com/lf426/archive/2008/04/26/48182.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>成员数据的三种形式与栈对象的生命周期</title><link>http://www.cppblog.com/lf426/archive/2008/04/14/47029.html</link><dc:creator>lf426</dc:creator><author>lf426</author><pubDate>Mon, 14 Apr 2008 04:36:00 GMT</pubDate><guid>http://www.cppblog.com/lf426/archive/2008/04/14/47029.html</guid><wfw:comment>http://www.cppblog.com/lf426/comments/47029.html</wfw:comment><comments>http://www.cppblog.com/lf426/archive/2008/04/14/47029.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/lf426/comments/commentRss/47029.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/lf426/services/trackbacks/47029.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 假设我们有一个类A，另外一个类B中有个成员数据是A的对象，我们如何来定义这个成员数据呢？<br>最直接的，我们可以就把它定义为A的对象：A a_obj;<br>其次，我们可以把它定义为A对象的引用：A&amp; a_obj; 或者const引用：const A&amp; a_obj;<br>再者，我们还可以把它定义为A对象的指针：A* pA_obj; 或者const对象的指针：const A* pA_obj;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 当我们直接使用A对象的时候，a_obj会在B对象建立的时候建立，在B销毁的时候销毁。因为这是一个新建立的对象，所以在成员初始化的时候是真正构造了对象，即我们前面说到的使用了复制构造函数。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 如果使用的是A对象的引用或者指针，a_obj（或pA_obj）都没有构造新的对象。我们假设B的一个构造函数是这样的：B(const A&amp; a_obj): a_obj(a_obj) {}，那么毫无疑问，这个构造函数是能正常工作的，也就是说，我们用现成的对象，或者说是在B对象生命周期内都会一直存在的A对象去构造B对象是没有问题的。但是，如果一个构造函数是这样的：B(int a): a_obj(A(a)) {}，这个函数，一般在编译的时候是不会报错或者发出警告的，但是我们分析一下，A(a)是临时构造了一个A对象，然后a_obj成为了这个临时对象的引用。但是问题是，这个临时对象在B对象构造之后就马上销毁了，也就是说，a_obj引用了一个不存在的对象（换到指针说就是指向了空指针）。这是一个巨大的错误，将在运行时引发错误。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 所以，结论是：如果成员数据使用（新）对象，则必须定义这个对象所属类的复制构造函数；如果使用的是对象引用或者指针，则一定只能用已经存在并且会在B对象整个生命周期内都存在的A对象来构造这个B对象。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 说得貌似很复杂，留个作为例子的3个类，大家可以多写几个演示程序试试。<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"><span style="COLOR: #000000">#ifndef&nbsp;A_HPP<br></span><span style="COLOR: #0000ff">#define</span><span style="COLOR: #000000">&nbsp;A_HPP</span><span style="COLOR: #000000"><br><br>#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">iostream</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br></span><span style="COLOR: #0000ff">using</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">namespace</span><span style="COLOR: #000000">&nbsp;std;<br><br></span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;get_point(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;lenth);<br></span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;free_point(</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;temp);<br><br></span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;A<br>{<br></span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000">:<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//<br></span><span style="COLOR: #0000ff">protected</span><span style="COLOR: #000000">:<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;temp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;lenth;<br>&nbsp;&nbsp;&nbsp;&nbsp;A();<br></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br>&nbsp;&nbsp;&nbsp;&nbsp;A(</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;copy);<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">~</span><span style="COLOR: #000000">A();<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;show()&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">;<br>};<br><br></span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;C:&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;A<br>{<br></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br>&nbsp;&nbsp;&nbsp;&nbsp;C(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;_lenth);<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">~</span><span style="COLOR: #000000">C();<br>};<br><br><br></span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;B<br>{<br></span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000">:<br>&nbsp;&nbsp;&nbsp;&nbsp;A&nbsp;b;<br></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br>&nbsp;&nbsp;&nbsp;&nbsp;B(</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;a);<br>&nbsp;&nbsp;&nbsp;&nbsp;B(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;_lenth);<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">~</span><span style="COLOR: #000000">B();<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;show()&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">;<br>};<br><br></span><span style="COLOR: #0000ff">#endif</span></div>
<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"><span style="COLOR: #000000">#include&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">a.hpp</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"><br><br>A::A():&nbsp;temp(</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">),lenth(</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;cout</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">A&nbsp;Constructor!</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;endl;&nbsp;<br>}<br><br><br>A::A(</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;copy):&nbsp;lenth(copy.lenth)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;temp&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;get_point(lenth);<br>&nbsp;&nbsp;&nbsp;&nbsp;cout&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">A&nbsp;Copy&nbsp;Constructor</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;endl;<br>&nbsp;&nbsp;&nbsp;&nbsp;cout&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">temp&nbsp;at:&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">(temp)&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;endl;<br>}<br><br><br>A::</span><span style="COLOR: #000000">~</span><span style="COLOR: #000000">A()<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;cout&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">temp&nbsp;at:&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">(temp)&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;endl;<br>&nbsp;&nbsp;&nbsp;&nbsp;free_point(temp);<br>&nbsp;&nbsp;&nbsp;&nbsp;cout&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Heap&nbsp;Deleted!\n</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;cout&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">A&nbsp;Destroyed!</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;endl;&nbsp;<br>}<br><br></span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;A::show()&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000"><br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;cout&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;temp&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;endl;<br>}<br><br><br></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">***************************************</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"><br><br>C::C(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;_lenth):&nbsp;A()<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;lenth&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;_lenth;<br>&nbsp;&nbsp;&nbsp;&nbsp;temp&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;get_point(lenth);<br>&nbsp;&nbsp;&nbsp;&nbsp;cout</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">C&nbsp;Constructor!</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;endl;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;cout&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">temp&nbsp;at:&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">(temp)&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;endl;<br>}<br><br>C::</span><span style="COLOR: #000000">~</span><span style="COLOR: #000000">C()<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;cout&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">C&nbsp;Destroyed!</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;endl;&nbsp;<br>}<br><br></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">***************************************</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"><br>&nbsp;<br>B::B(</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;a):&nbsp;b(a)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;cout</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">B&nbsp;Constructor!</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;endl;&nbsp;<br>}<br><br>B::B(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;_lenth):&nbsp;b(C(_lenth))<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;cout</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">B&nbsp;Constructor!</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;endl;<br>}<br><br>B::</span><span style="COLOR: #000000">~</span><span style="COLOR: #000000">B()<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;cout&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">B&nbsp;Destroyed!</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;endl;&nbsp;<br>}<br><br></span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;B::show()&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000"><br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;b.show();<br>}<br><br><br></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">************************************</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"><br><br></span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;get_point(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;lenth)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;temp&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">[lenth</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">];<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000">&nbsp;(&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;i&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;&nbsp;i</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">&nbsp;lenth;&nbsp;i</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">&nbsp;)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;temp[i]&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">'</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">'</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;temp[lenth]&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">'</span><span style="COLOR: #000000">\0</span><span style="COLOR: #000000">'</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;cout&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">New&nbsp;buffer&nbsp;got!\n</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;temp;<br>}<br><br></span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;free_point(</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;temp)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;delete&nbsp;[]temp;<br>&nbsp;&nbsp;&nbsp;&nbsp;cout&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Buffer&nbsp;deleted!\n</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br>}</span></div>
<img src ="http://www.cppblog.com/lf426/aggbug/47029.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/lf426/" target="_blank">lf426</a> 2008-04-14 12:36 <a href="http://www.cppblog.com/lf426/archive/2008/04/14/47029.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>创建一次销毁两次？！复制构造函数的致命错误。</title><link>http://www.cppblog.com/lf426/archive/2008/04/14/47025.html</link><dc:creator>lf426</dc:creator><author>lf426</author><pubDate>Mon, 14 Apr 2008 03:50:00 GMT</pubDate><guid>http://www.cppblog.com/lf426/archive/2008/04/14/47025.html</guid><wfw:comment>http://www.cppblog.com/lf426/comments/47025.html</wfw:comment><comments>http://www.cppblog.com/lf426/archive/2008/04/14/47025.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/lf426/comments/commentRss/47025.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/lf426/services/trackbacks/47025.html</trackback:ping><description><![CDATA[<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; C++为我们提供了默认的复制构造函数，赋值函数和析构函数，使用的全部是&#8220;浅复制&#8221;，即仅仅复制栈上的数据。换句话说，如果我们涉及到了对堆数据的操作，这些函数都必须我们自己重新来写。我很郁闷为什么在编译的时候，C++不能自己发现构造函数使用了堆操作，从而提醒不要使用默认的这三个函数。也许是因为要编译器做到智能的判断很难吧。用new...delete或许很容易看出来，但是更多的函数调用，特别是涉及到C风格的函数的时候，真的很难判断哪些函数使用到了堆操作。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 而这三个函数的作用可以说是巨大的！析构就不说了，析构可以说是C++永远的痛。复制构造函数用得最多的地方，恐怕就是成员初始化列表的时候，这几乎是在一个类成员数据使用到另外一个类对象时候的唯一方法。而赋值函数则是把数据从语句体（&#8220;{}&#8221;对，循环，判断）中带出的最简单方法——虽然我们现在可以很方便的使用vector。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 这里先说说复制构造函数吧。如果遗漏申明，又不慎用到，比如这个例子：</p>
<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"><span style="COLOR: #000000">#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">iostream</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br>#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">vector</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><br></span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;A<br>{<br></span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000">:<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;a;<br></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br>&nbsp;&nbsp;&nbsp;&nbsp;A(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;_a):&nbsp;a(_a)<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::cout&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">A&nbsp;created!\n</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br></span><span style="COLOR: #008000">/*</span><span style="COLOR: #008000"><br>&nbsp;&nbsp;&nbsp;&nbsp;A(const&nbsp;A&amp;&nbsp;copy):&nbsp;a(copy.a)<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::cout&nbsp;&lt;&lt;&nbsp;"A&nbsp;copy&nbsp;created!\n";<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br></span><span style="COLOR: #008000">*/</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">~</span><span style="COLOR: #000000">A()<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::cout&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">A&nbsp;destroyed!\n</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;show()&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::cout&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;a&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;std::endl;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>};<br><br></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;main(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;argc,&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;argv[])<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;A&nbsp;a(</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">);<br>&nbsp;&nbsp;&nbsp;&nbsp;A&nbsp;b(a);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br>}</span></div>
那么，结果运行就会出现貌似创建一次，但是却销毁了两次的假象。这当然是不可能发生的，但是郁闷的是，C++中的构造和析构不总是成对出现的，比如我们前面说到的手动显式调用析构函数的情况。所以，如果放在大的项目中，这为我们的调试带来更多的困难。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 所以，结论是，如果A类构造具有堆操作，有可能把A类作为B类的成员数据，B类又有可能通过成员初始化列表构造A对象，请一定别忘记手写复制构造函数。 
<img src ="http://www.cppblog.com/lf426/aggbug/47025.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/lf426/" target="_blank">lf426</a> 2008-04-14 11:50 <a href="http://www.cppblog.com/lf426/archive/2008/04/14/47025.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>显式析构函数的陷阱</title><link>http://www.cppblog.com/lf426/archive/2008/04/12/46909.html</link><dc:creator>lf426</dc:creator><author>lf426</author><pubDate>Sat, 12 Apr 2008 06:29:00 GMT</pubDate><guid>http://www.cppblog.com/lf426/archive/2008/04/12/46909.html</guid><wfw:comment>http://www.cppblog.com/lf426/comments/46909.html</wfw:comment><comments>http://www.cppblog.com/lf426/archive/2008/04/12/46909.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/lf426/comments/commentRss/46909.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/lf426/services/trackbacks/46909.html</trackback:ping><description><![CDATA[<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 几乎在大部分时候，我们是不需要显式的调用析构函数的。显式的调用析构函数是一件非常危险的事情，因为如果系统会调用析构函数，无论我们自己是否已经调用过，仍然会再次调用。换句话说，我们自己所谓的显式调用析构函数，实际上只是调用了一个成员函数，并没有真正意义上的让对象&#8220;析构&#8221;。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 为了理解这个问题，我们必须首先弄明白&#8220;堆&#8221;和&#8220;栈&#8221;的概念。<br>堆区（heap）&nbsp;—— 一般由程序员分配释放， 若程序员不释放，程序结束时可能由OS回收 。注意它与数据结构中的堆是两回事，分配方式倒是类似于链表。<br>栈区（stack）—— 由编译器自动分配释放 ，存放函数的参数值，局部变量的值等。其操作方式类似于数据结构中的栈。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 我们构造对象，往往都是在一段语句体中，比如函数，判断，循环，还有就直接被一对&#8220;{}&#8221;包含的语句体。这个对象在语句体中被创建，在语句体结束的时候被销毁。问题就在于，这样的对象在生命周期中是存在于栈上的。也就是说，如何管理，是系统完成而程序员不能控制的。所以，即使我们调用了析构，在对象生命周期结束后，系统仍然会再调用一次析构函数，将其在栈上销毁，实现真正的析构。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 所以，如果我们在析构函数中有清除堆数据的语句，调用两次意味着第二次会试图清理已经被清理过了的，根本不再存在的数据！这是件会导致运行时错误的问题，并且在编译的时候不会告诉你！<br>在网上找到这几句话，说得很好啊：<br><span style="COLOR: #666699">//显式调用的时候，析构函数相当于的一个普通的成员函数<br>//编译器隐式调用析构函数，如分配了对内存，显式调用析构的话引起重复释放堆内存的异常<br>//把一个对象看作占用了部分栈内存，占用了部分堆内存（如果申请了的话），这样便于理解这个问题<br>//系统隐式调用析构函数的时候，会加入释放栈内存的动作（而堆内存则由用户手工的释放）<br>//用户显式调用析构函数的时候，只是单纯执行析构函数内的语句，不会释放栈内存，摧毁对象</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 系统在什么情况下不会自动调用析构函数呢？显然，如果对象被建立在堆上，系统就不会自动调用。一个常见的例子是new...delete组合。但是好在调用delete的时候，析构函数还是被自动调用了。很罕见的例外在于使用布局new的时候，在delete设置的缓存之前，需要显式调用的析构函数，这实在是很少见的情况。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 所以，结论是，一般不要自作聪明的去调用析构函数。或者要是你不嫌麻烦的话，析构之前最好先看看堆上的数据是不是已经被释放过了。放出一个演示的例子，大家可以参考一下哈。</p>
<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"><span style="COLOR: #000000">#ifndef&nbsp;A_HPP<br></span><span style="COLOR: #0000ff">#define</span><span style="COLOR: #000000">&nbsp;A_HPP</span><span style="COLOR: #000000"><br><br>#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">iostream</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br></span><span style="COLOR: #0000ff">using</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">namespace</span><span style="COLOR: #000000">&nbsp;std;<br><br></span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;A<br>{<br></span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000">:<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;a;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;temp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">bool</span><span style="COLOR: #000000">&nbsp;heap_deleted;<br></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br>&nbsp;&nbsp;&nbsp;&nbsp;A(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;_a);<br>&nbsp;&nbsp;&nbsp;&nbsp;A(</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;_a);<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">~</span><span style="COLOR: #000000">A();<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;change(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;x);<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;show()&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">;<br>};<br><br></span><span style="COLOR: #0000ff">#endif</span><span style="COLOR: #000000"><br></span></div>
<p><br>&nbsp;</p>
<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"><span style="COLOR: #000000">#include&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">a.hpp</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"><br><br>A::A(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;_a):&nbsp;heap_deleted(</span><span style="COLOR: #0000ff">false</span><span style="COLOR: #000000">)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;temp&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">temp&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;_a;<br>&nbsp;&nbsp;&nbsp;&nbsp;a&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">temp;<br>&nbsp;&nbsp;&nbsp;&nbsp;cout</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">A&nbsp;Constructor!</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;endl;&nbsp;<br>}<br><br>A::A(</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;_a):&nbsp;heap_deleted(<span style="COLOR: #0000ff">false</span>)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;temp&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">temp&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;_a.a;<br>&nbsp;&nbsp;&nbsp;&nbsp;a&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">temp;<br>&nbsp;&nbsp;&nbsp;&nbsp;cout&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">A&nbsp;Copy&nbsp;Constructor</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;endl;<br>}<br><br>A::</span><span style="COLOR: #000000">~</span><span style="COLOR: #000000">A()<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;(&nbsp;heap_deleted&nbsp;</span><span style="COLOR: #000000">==</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">false</span><span style="COLOR: #000000">){<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cout&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">temp&nbsp;at:&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;temp&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;endl;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;delete&nbsp;temp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;heap_deleted&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">true</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cout&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Heap&nbsp;Deleted!\n</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">else</span><span style="COLOR: #000000">&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cout&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Heap&nbsp;&nbsp;already&nbsp;Deleted!\n</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;cout&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">A&nbsp;Destroyed!</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;endl;&nbsp;<br>}<br><br></span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;A::change(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;x)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;a&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;x;<br>}<br><br></span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;A::show()&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000"><br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;cout&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">a&nbsp;=&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;a&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;endl;<br>}</span></div>
<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"><span style="COLOR: #000000">#include&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">a.hpp</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"><br><br></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;main(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;argc,&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;argv[])<br>{<br><br>&nbsp;&nbsp;&nbsp;&nbsp;A&nbsp;a(</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">);<br>&nbsp;&nbsp;&nbsp;&nbsp;a.</span><span style="COLOR: #000000">~</span><span style="COLOR: #000000">A();<br>&nbsp;&nbsp;&nbsp;&nbsp;a.show();<br>&nbsp;&nbsp;&nbsp;&nbsp;cout&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">main()&nbsp;end\n</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;a.change(</span><span style="COLOR: #000000">2</span><span style="COLOR: #000000">);<br>&nbsp;&nbsp;&nbsp;&nbsp;a.show();<br><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br>}</span></div>
<img src ="http://www.cppblog.com/lf426/aggbug/46909.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/lf426/" target="_blank">lf426</a> 2008-04-12 14:29 <a href="http://www.cppblog.com/lf426/archive/2008/04/12/46909.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>SDL入门教程（九）：4、int转换为std::string</title><link>http://www.cppblog.com/lf426/archive/2008/03/26/45459.html</link><dc:creator>lf426</dc:creator><author>lf426</author><pubDate>Wed, 26 Mar 2008 12:48:00 GMT</pubDate><guid>http://www.cppblog.com/lf426/archive/2008/03/26/45459.html</guid><wfw:comment>http://www.cppblog.com/lf426/comments/45459.html</wfw:comment><comments>http://www.cppblog.com/lf426/archive/2008/03/26/45459.html#Feedback</comments><slash:comments>6</slash:comments><wfw:commentRss>http://www.cppblog.com/lf426/comments/commentRss/45459.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/lf426/services/trackbacks/45459.html</trackback:ping><description><![CDATA[作者：龙飞<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 我下面考虑的问题，是用TextSurface反馈鼠标事件的信息。我想到的第一个例子，很自然就是反馈鼠标所在坐标的位置。这里涉及到一个基础的问题，即鼠标位置显然不是用字符串表示的。SDL给我们的反馈信息是int，我们需要用TextSurface将int构建成可以被blit到ScreenSurface上的面，需要做的第一件事情，是将int转换为string。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 我的思路是这样的：首先找到int的数位数；然后依次从高位读取数字，之后将这个位去掉（通常减掉是最简单的）；依次记录这些数字，转换成string，然后将这些数字&#8220;加&#8221;（字符串的合并）起来。<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"><span style="COLOR: #008000">//</span><span style="COLOR: #008000">UVi&nbsp;Soft&nbsp;(2008)<br></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">Long&nbsp;Fei&nbsp;(lf426),&nbsp;E-mail:&nbsp;zbln426@163.com<br><br></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">FileName:&nbsp;int_to_string.h</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"><br>#<span style="COLOR: #0000ff">ifndef</span>&nbsp;INT_TO_STRING_H_<br></span><span style="COLOR: #0000ff">#define</span><span style="COLOR: #000000">&nbsp;INT_TO_STRING_H_</span><span style="COLOR: #000000"><br><br>#<span style="COLOR: #0000ff">include</span>&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">iostream</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br>#<span style="COLOR: #0000ff">include</span>&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br>#<span style="COLOR: #0000ff">include</span>&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">vector</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><br></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;int_power(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">base</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;exp);<br>std::</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">&nbsp;int_to_string(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;num);<br><br></span><span style="COLOR: #0000ff">#endif</span></div>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 其中，int_to_string()是我们需要构建的函数，int_power()是求一个数的整数幂的函数。这么简单的算法，我们就自己写吧。至于用到vector，按照我的思路，我们需要的数据结构显然应该是&#8220;队列&#8221;（先进先出）。不过真得感谢STL，用vector显然不是最优化的，但是肯定是最&#8220;通俗&#8221;的，因为即使是作为非专业的队列（或者栈），vector也已经为我们提供了必要的方法，比如推入（push_back）。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 下面我就把程序说明夹在程序中间了。原因是本人英语太菜，简单描述还能忍，描述算法就有点不能忍了-_-!!!。另外，尽管我英语这水平，我还是希望程序里面别用中文注释的好。这种事情，您见过一次乱码，就总是得恶心一辈子。<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"><span style="COLOR: #008000">//</span><span style="COLOR: #008000">UVi&nbsp;Soft&nbsp;(2008)<br></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">Long&nbsp;Fei&nbsp;(lf426),&nbsp;E-mail:&nbsp;zbln426@163.com</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000"><br>#include&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">int_to_string.h</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"><br><br></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;int_power(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">base</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;exp)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;result&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000">&nbsp;(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;i&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;exp;&nbsp;i&nbsp;</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;&nbsp;i</span><span style="COLOR: #000000">--</span><span style="COLOR: #000000">&nbsp;)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;result</span><span style="COLOR: #000000">*=</span><span style="COLOR: #0000ff">base</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;result;<br>}</span></div>
这是个很简单的求幂的算法。其实我们在程序中，只需要用到求10的n次幂，所以，实际上我们还可以写得更加有针对一点。<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"><span style="COLOR: #000000">std::</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">&nbsp;int_to_string(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;num)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">bool</span><span style="COLOR: #000000">&nbsp;negative&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">false</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;(&nbsp;num&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">&nbsp;){<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;negative&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">true</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;num&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">num;<br>&nbsp;&nbsp;&nbsp;&nbsp;}</span></div>
这开始写转换函数了。首先我们判定int是否为负。如果是，我们把它变成其相反数，然后与正数一样转换，最后在前面加上&#8220;-&#8221;就OK了。<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"><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;bitNum&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000">&nbsp;(&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;i&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;num;&nbsp;i&nbsp;</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">9</span><span style="COLOR: #000000">;&nbsp;i</span><span style="COLOR: #000000">/=</span><span style="COLOR: #000000">10</span><span style="COLOR: #000000">&nbsp;)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bitNum</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">;</span></div>
bitNum是这个int的数位数。比如3就是1位，1024就是4位。<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"><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;std::vector</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;eachNum;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000">&nbsp;(&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;i&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;bitNum,&nbsp;temp&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;num;&nbsp;i&nbsp;</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;&nbsp;i</span><span style="COLOR: #000000">--</span><span style="COLOR: #000000">&nbsp;){<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;highBit&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">(temp</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">int_power(</span><span style="COLOR: #000000">10</span><span style="COLOR: #000000">,&nbsp;(i</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">)));<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;eachNum.push_back(highBit);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;temp</span><span style="COLOR: #000000">-=</span><span style="COLOR: #000000">(highBit</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">int_power(</span><span style="COLOR: #000000">10</span><span style="COLOR: #000000">,&nbsp;(i</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">)));<br>&nbsp;&nbsp;&nbsp;&nbsp;}</span></div>
我们通过vector数组纪录每个数位上的数字，从高位到低位。需要说明的是，n位的数字是10的n-1次方幂。比如1024是4位，而1000是10的3次方幂。所以，我们这里用的是i-1而非i。<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"><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;std::</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">&nbsp;str;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;(&nbsp;negative&nbsp;</span><span style="COLOR: #000000">==</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">true</span><span style="COLOR: #000000">&nbsp;)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;str&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000">&nbsp;(&nbsp;std::vector</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">::iterator&nbsp;pTemp&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;eachNum.begin();&nbsp;pTemp&nbsp;</span><span style="COLOR: #000000">!=</span><span style="COLOR: #000000">&nbsp;eachNum.end();&nbsp;pTemp</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">&nbsp;){<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">switch</span><span style="COLOR: #000000">&nbsp;(&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">pTemp&nbsp;){<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">case</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;str</span><span style="COLOR: #000000">+=</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">break</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">case</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;str</span><span style="COLOR: #000000">+=</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">break</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">case</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">2</span><span style="COLOR: #000000">:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;str</span><span style="COLOR: #000000">+=</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">2</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">break</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">case</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">3</span><span style="COLOR: #000000">:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;str</span><span style="COLOR: #000000">+=</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">3</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">break</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">case</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">4</span><span style="COLOR: #000000">:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;str</span><span style="COLOR: #000000">+=</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">4</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">break</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">case</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">5</span><span style="COLOR: #000000">:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;str</span><span style="COLOR: #000000">+=</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">5</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">break</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">case</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">6</span><span style="COLOR: #000000">:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;str</span><span style="COLOR: #000000">+=</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">6</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">break</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">case</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">7</span><span style="COLOR: #000000">:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;str</span><span style="COLOR: #000000">+=</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">7</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">break</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">case</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">8</span><span style="COLOR: #000000">:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;str</span><span style="COLOR: #000000">+=</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">8</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">break</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">case</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">9</span><span style="COLOR: #000000">:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;str</span><span style="COLOR: #000000">+=</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">9</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">break</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">default</span><span style="COLOR: #000000">:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">break</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;str;<br>}</span></div>
最后，我们用了STL的方法将每个数字转换成std::string的字符串，然后将这些字符串合并起来，作为函数的返回值。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 我们在下一节中将用TextSurface演示这个函数的作用，以及实现我们在本节前面所提出的问题。
<img src ="http://www.cppblog.com/lf426/aggbug/45459.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/lf426/" target="_blank">lf426</a> 2008-03-26 20:48 <a href="http://www.cppblog.com/lf426/archive/2008/03/26/45459.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>从“集合”实例分析修饰函数返回值的const作用</title><link>http://www.cppblog.com/lf426/archive/2008/03/13/44360.html</link><dc:creator>lf426</dc:creator><author>lf426</author><pubDate>Thu, 13 Mar 2008 05:30:00 GMT</pubDate><guid>http://www.cppblog.com/lf426/archive/2008/03/13/44360.html</guid><wfw:comment>http://www.cppblog.com/lf426/comments/44360.html</wfw:comment><comments>http://www.cppblog.com/lf426/archive/2008/03/13/44360.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.cppblog.com/lf426/comments/commentRss/44360.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/lf426/services/trackbacks/44360.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 这段时间在复习C++基础，算法与数据结构，以及学习STL。所以，SDL的教程更新会慢些。因为我还是以自己的项目为核心进行学习的，所以基础知识和游戏设计涉及到图形，控制和多线程的内容学习，应该是会有些交叉的。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 发现这个问题，是因为一直以来思考的一个算法——关于&#8220;集合&#8221;的实现。这个集合就是数学中的集合，与计算机中数列一个最大的不同在于，集合的元素是互异的。因为这两天在熟悉vector，所以觉得用vector实现集合再合适不过了。STL确实是很好很强大的体系，无论是内存管理，还是链表的实现，让我们可以省很多心。其实关于为什么要实现集合，也是因为我在计划实现类似英雄无敌战场计算移动的一系列算法中，很多地方会用到集合的概念，甚至包括并集和差集等等。也许我想到的算法是很笨拙的，但是在我还没有完全阅读相关的已有代码之前，觉得完全凭自己的认识，实现这些算法还是很有意义的，所以，从学习C++的第一天开始，我就在试图找到解决这些问题的方法，而现在，越来越清晰了，呵呵。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 我的思路很直接也很简单，就是把一个数组中的元素往一个新的数组中填，新填充的元素会遍历新数组中已有的元素，如果与之互异，则填入（push），否则就跳到下一个。以上就已经确立了成员数据（私有）和构造函数。因为我们需要&#8220;集合化&#8221;了的数组是可以被外部访问的，所以一个最简单的方法就是把成员数据公有——这确实是很简单，而且这样就不会出现今天我们要讨论的问题了；另外一个笨办法是用一个公有方法，返回成员数据的值——我就是这么做的，因为这貌似更符合OOP的&#8220;数据隐藏&#8221;的精神-_-!!!。很快可以写出头文件：<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"><span style="COLOR: #000000">#<span style="COLOR: #0000ff">ifndef</span>&nbsp;AGGREGATE_H_<br></span><span style="COLOR: #0000ff">#define</span><span style="COLOR: #000000">&nbsp;AGGREGATE_H_</span><span style="COLOR: #000000"><br><br>#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">iostream</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br>#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">vector</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br>#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">algorithm</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><br></span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;Aggregate<br>{<br></span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000">:<br>&nbsp;&nbsp;&nbsp;&nbsp;std::vector</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;agg;<br></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br>&nbsp;&nbsp;&nbsp;&nbsp;Aggregate(std::vector</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&gt;&amp;</span><span style="COLOR: #000000">&nbsp;temp);<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: red">const</span><span style="COLOR: #000000">&nbsp;std::vector</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;getAgg()&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">;<br>};<br><br></span><span style="COLOR: #0000ff">#endif</span></div>
请注意那个红色的const，其实我想说的是，第一次写这个程序的时候，我并没有这个const。一直以来，除了在重载&#8220;=&#8221;的时候我大概清楚修饰返回值const的作用是可以避免让返回值做左值，其他时候还真不太明白这个const的作用，只是本着C++的精神——能const就const吧-_-!!!。实现文件：<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"><span style="COLOR: #000000">#<span style="COLOR: #0000ff">include</span>&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">aggregate.h</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"><br><br>Aggregate::Aggregate(std::vector</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&gt;&amp;</span><span style="COLOR: #000000">&nbsp;temp)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000">&nbsp;(&nbsp;std::vector</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">::iterator&nbsp;pTemp&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;temp.begin();&nbsp;pTemp&nbsp;</span><span style="COLOR: #000000">!=</span><span style="COLOR: #000000">&nbsp;temp.end();&nbsp;pTemp</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">&nbsp;)&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">bool</span><span style="COLOR: #000000">&nbsp;findSame&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">false</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000">&nbsp;(&nbsp;std::vector</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">::iterator&nbsp;pAgg&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;agg.begin();&nbsp;pAgg&nbsp;</span><span style="COLOR: #000000">!=</span><span style="COLOR: #000000">&nbsp;agg.end();&nbsp;pAgg</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">&nbsp;)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;(&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">pTemp&nbsp;</span><span style="COLOR: #000000">==</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">pAgg&nbsp;)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;findSame&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">true</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;(&nbsp;findSame&nbsp;</span><span style="COLOR: #000000">==</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">false</span><span style="COLOR: #000000">&nbsp;)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;agg.push_back(</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">pTemp);<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>}<br><br></span><span style="COLOR: red">const</span><span style="COLOR: #000000">&nbsp;std::vector</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;Aggregate::getAgg()&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000"><br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;agg;<br>}</span></div>
一切都很完美，不是吗？顺手就继续写出一个测试用的程序：<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">#<span style="COLOR: #0000ff">include</span>&nbsp;"aggregate.h"<br><br><span style="COLOR: #0000ff">void</span>&nbsp;show(<span style="COLOR: #0000ff">int</span>&amp;&nbsp;i);<br><br><span style="COLOR: #0000ff">int</span>&nbsp;main(<span style="COLOR: #0000ff">int&nbsp;</span>argc,&nbsp;<span style="COLOR: #0000ff">char</span>*&nbsp;argv[])<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;std::vector&lt;<span style="COLOR: #0000ff">int</span>&gt;&nbsp;tempArray;<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000ff">int&nbsp;</span>temp;<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000ff">bool&nbsp;</span>goon&nbsp;=&nbsp;<span style="COLOR: #0000ff">true</span>;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000ff">while</span>&nbsp;(&nbsp;goon&nbsp;==&nbsp;<span style="COLOR: #0000ff">true</span>&nbsp;)&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::cout&nbsp;&lt;&lt;&nbsp;"#"&nbsp;&lt;&lt;&nbsp;tempArray.size()+1&nbsp;&lt;&lt;&nbsp;"=&nbsp;";<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::cin&nbsp;&gt;&gt;&nbsp;temp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000ff">if&nbsp;</span>(&nbsp;temp&nbsp;==&nbsp;-1&nbsp;)&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;goon&nbsp;=&nbsp;<span style="COLOR: #0000ff">false</span>;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000ff">continue</span>;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tempArray.push_back(temp);<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;std::cout&nbsp;&lt;&lt;&nbsp;"You've&nbsp;entered&nbsp;"&nbsp;&lt;&lt;&nbsp;tempArray.size()&nbsp;&lt;&lt;&nbsp;"&nbsp;numbers."&nbsp;&lt;&lt;&nbsp;std::endl;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;for_each(tempArray.begin(),&nbsp;tempArray.end(),&nbsp;show);<br><br><span style="COLOR: #800080">&nbsp;&nbsp;&nbsp;&nbsp;std::cout&nbsp;&lt;&lt;&nbsp;"----------------------------\n"&nbsp;&lt;&lt;&nbsp;"Now,&nbsp;to&nbsp;be&nbsp;aggregate<img src="http://www.cppblog.com/Images/dot.gif">\n";<br><br>&nbsp;&nbsp;&nbsp;&nbsp;Aggregate&nbsp;tempAgg&nbsp;(tempArray);<br>&nbsp;&nbsp;&nbsp;&nbsp;std::cout&nbsp;&lt;&lt;&nbsp;"There&nbsp;are&nbsp;"&nbsp;&lt;&lt;&nbsp;tempAgg.getAgg().size()&nbsp;&lt;&lt;&nbsp;"&nbsp;different&nbsp;numbers.\n";<br>&nbsp;&nbsp;&nbsp;&nbsp;for_each(tempAgg.getAgg().begin(),&nbsp;tempAgg.getAgg().end(),&nbsp;show);</span><br><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000ff">return</span>&nbsp;0;<br>}<br><br><span style="COLOR: #0000ff">void</span>&nbsp;show(<span style="COLOR: #0000ff">int</span>&amp;&nbsp;i)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;std::cout&nbsp;&lt;&lt;&nbsp;i&nbsp;&lt;&lt;&nbsp;std::endl;<br>}<br></div>
很不幸，编译正常的通过了（注意，没有红色的const的时候）。<br>但是，运行时出现了错误。<br>运行时错误是件令人很郁闷的事情，因为这意味着编译器不会帮你找到出错的地方。<br>幸运的是，直觉让我觉得类似tempAgg.getAgg().begin()的用法有问题，所以，我改成了：（紫色那部分代码）<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"><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;std::cout&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">----------------------------\n</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Now,&nbsp;to&nbsp;be&nbsp;aggregate<img src="http://www.cppblog.com/Images/dot.gif">\n</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;Aggregate&nbsp;tempAgg&nbsp;(tempArray);<br>&nbsp;&nbsp;&nbsp;&nbsp;std::vector</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;tempAggArray&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;tempAgg.getAgg();<br>&nbsp;&nbsp;&nbsp;&nbsp;std::cout&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">There&nbsp;are&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;tempAggArray.size()&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;different&nbsp;numbers.\n</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;for_each(tempAggArray.begin(),&nbsp;tempAggArray.end(),&nbsp;show);</span></div>
这样，问题是解决了。但是我们回头分析一下，刚才的问题到底出在什么地方呢？<br>其实，如果我们加上红色的const，使用原来的代码进行编译的时候，编译器是可以指出我们的错误的，确实是tempAgg.getAgg().begin()的用法出了问题。具体的原因包含在&lt;algorithm&gt;里面，我没有仔细去分析，但是我们至少明白了，方法begin()会试图修改其对象的返回值！<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 让错误被发现在编译阶段，远远好于被发现在运行时阶段。我想，这就是C++中const最大的作用。所以，总结起来还是C++的一句话，能const，就const吧。:) 
<img src ="http://www.cppblog.com/lf426/aggbug/44360.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/lf426/" target="_blank">lf426</a> 2008-03-13 13:30 <a href="http://www.cppblog.com/lf426/archive/2008/03/13/44360.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>