﻿<?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++博客-Ogre-文章分类-游戏通用编程</title><link>http://www.cppblog.com/windeer/category/929.html</link><description>        ——静下心，坐坐……</description><language>zh-cn</language><lastBuildDate>Sun, 29 Mar 2009 21:34:09 GMT</lastBuildDate><pubDate>Sun, 29 Mar 2009 21:34:09 GMT</pubDate><ttl>60</ttl><item><title>C＋＋中更好地使用Singleton(单件)模式</title><link>http://www.cppblog.com/windeer/articles/78276.html</link><dc:creator>alpha</dc:creator><author>alpha</author><pubDate>Sun, 29 Mar 2009 09:07:00 GMT</pubDate><guid>http://www.cppblog.com/windeer/articles/78276.html</guid><wfw:comment>http://www.cppblog.com/windeer/comments/78276.html</wfw:comment><comments>http://www.cppblog.com/windeer/articles/78276.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/windeer/comments/commentRss/78276.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/windeer/services/trackbacks/78276.html</trackback:ping><description><![CDATA[<h2>C＋＋中更好地使用Singleton(单件)模式</h2>
<input id=search-key type=hidden value=C＋＋中更好地使用Singleton(单件)模式 name=search-key>
<div class="rl entry-titlerl fenlei-Span">分类:<a href="http://erisenxu.bokee.com/cat.10227207.html"><font color=#03354f>设计模式</font></a></div>
<div class=fbzt><span class=f><span class=pub-date title=发布日期>2006.7.22</span> <span class=pub-time title=发布时间>17:50</span> <span class=ln-author>作者：<a class=author href="http://id.bokee.com/showInfo.b?username=erisenxu.bokee.com"><font color=#03354f>黑猫侦探</font></a></span> | <a class=author href="http://erisenxu.bokee.com/viewdiary.12125852.html#remark"><font color=#03354f>评论：0</font></a> | <span class=ln-viewed id=h12125852>阅读：776</span> </span></div>
<div class="entry-body nerr">
<p>所谓Singleton模式，其主要作用是保证在应用程序中，一个类Class只有一个实例存在。 在软件开发中，Singleton模式应该是使用比较广泛的一个模式了，例如，实现Log系统的类、全局配置的类，以及建立目录、数据库连接的类、全局统计的类等等，都可以使用Singleton模式来实现。因为通常这些类，只允许一个实例存在，而且该实例可以在其他任何对象、任何函数中都可以被调用。</p>
<p>在C＋＋中使用Singleton模式，要注意的问题，也是如何管理该对象所使用的内存了，呵呵！对内存的管理，真的是一个老生常谈的事情，可是又不得不考虑！是呀，Singleton对象的内存怎么释放呢？因为该对象通常是为系统中所有其他对象服务的，而C＋＋中又没有垃圾回收机制。正因为如此，很多人选择不释放其内存，因为通常Singleton对象的生命周期，会一直到应用程序运行结束，程序结束后，可以由操作系统来回收内存。当前，大多数的操作系统都可以完成这个工作，可这实在不是一个好习惯。</p>
<p>有没有更好的方法呢？当然有，那就是不要使用指针，即，不要象《设计模式》这本书里面叙述的那样实现Singleton，而是如下来实现：</p>
<p><font color=#0000ff>class</font> SingletonTest</p>
<p>{</p>
<p><font color=#0000ff>protected</font>:</p>
<p>&nbsp;&nbsp;&nbsp; SingletonTest() {}&nbsp;<font color=#008000>// 将构造函数保护起来</font></p>
<p>public</p>
<p>&nbsp;&nbsp;&nbsp; <font color=#0000ff>static</font> SingletonTest&amp; getInstance(); <font color=#008000>// 使用instance来创建对象</font></p>
<p>};</p>
<p>SingletonTest&amp; SingletonTest::getInstance()<br>{<br>&nbsp;&nbsp;&nbsp; <font color=#0000ff>static</font> SingletonTest&nbsp;instance; <font color=#008000>// 申明对象时，使用static</font><br>&nbsp;&nbsp;&nbsp; <font color=#0000ff>return</font> instance;<br>}</p>
<p>使用该对象的方法如下：</p>
<p>&nbsp;&nbsp;&nbsp; SingletonTest::getInstance().函数名;</p>
<p>或：</p>
<p>&nbsp;&nbsp;&nbsp; SingletonTest* test = &amp;SingletonTest::SingletonTest();</p>
<p>&nbsp;&nbsp;&nbsp; test-&gt;函数名</p>
<p>由于getInstance中，申明对象时使用了static，所以调用getInstance只会运行一次申明对象的那条语句，也就是，只会在系统中创建一个SingletonTest实例，又由于所创建的SingletonTest实例不是指针，在程序结束时，会将内存释放给操作系统。</p>
<p>&nbsp;</p>
</div><img src ="http://www.cppblog.com/windeer/aggbug/78276.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/windeer/" target="_blank">alpha</a> 2009-03-29 17:07 <a href="http://www.cppblog.com/windeer/articles/78276.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>  VC 之 Checked Iterator</title><link>http://www.cppblog.com/windeer/articles/78249.html</link><dc:creator>alpha</dc:creator><author>alpha</author><pubDate>Sun, 29 Mar 2009 04:08:00 GMT</pubDate><guid>http://www.cppblog.com/windeer/articles/78249.html</guid><wfw:comment>http://www.cppblog.com/windeer/comments/78249.html</wfw:comment><comments>http://www.cppblog.com/windeer/articles/78249.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/windeer/comments/commentRss/78249.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/windeer/services/trackbacks/78249.html</trackback:ping><description><![CDATA[<p>&nbsp;&nbsp;&nbsp; VC 之 Checked Iterator<br>&nbsp;&nbsp;&nbsp; 作者：tyc611.cublog.cn，2008-08-27</p>
<p>--------------------------------------------------------------------------------<br>&nbsp;&nbsp;&nbsp; Checked Iterator是指具有越界检查功能的迭代器，并且会在检查到越界操作时触发运行时错误处理（调用非法参数处理例程或者抛出异常）。VC从VS2005 开始支持Checked Iterator。另外，VC还支持Debug Iterator，有更多的检查功能，这里不予讨论。</p>
<p><br>--------------------------------------------------------------------------------<br>Part One 编译</p>
<p>&nbsp;&nbsp;&nbsp; Checked Iterator能够确保迭代器不会发生越界访问（如果发生越界访问，则会进行相应的处理）。如果在需要Checked Iterator的地方使用了非Checked Iterator，则在编译时会产生编译警告C4996（Level 3）。如果需要禁用此警告，可以通过定义宏_SCL_SECURE_NO_WARNINGS来达到目的。</p>
<p>#define _SCL_SECURE_NO_WARNING<br>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp; 可以通过定义宏_SECURE_SCL的值来启用/禁用Checked Iterator的检查功能。如果宏_SECURE_SCL被定义为1，则启用Checked Iterator的检查功能；如果宏_SECURE_SCL被定义为0，则禁用Checked Iterator的检查功能。如果Checked Iterator发现迭代器越界，则会触发运行时错误，该运行时错误的具体行为与宏_SECURE_SCL_THROWS的值相关。默认情况下，_SECURE_SCL的值为1。（注：Checked Iterator功能的启用与禁用和Debug Iterator功能的启用与禁用之间不会彼此影响）</p>
<p>&nbsp;&nbsp;&nbsp; 宏_SECURE_SCL_THROWS的值决定了Checked Iterator在发现越界时的运行时报错方式。如果_SECURE_SCL_THROWS被定义为1，则Checked Iterator在发现越界时会抛出异常std::out_of_rangce；如果_SECURE_SCL_THROWS被定义为0，则会调用CRT的非法参数处理例程（默认是终止程序）。宏_SECURE_SCL_THROWS的默认值为0。由于CRT的非法参数处理例程可以自行设置，所以程序可以改变默认终止运行的行为。（注：只有在_SECURE_SCL被定义为1时，_SECURE_SCL_THROWS才起作用）</p>
<p><br>--------------------------------------------------------------------------------<br>示例代码如下：<br>// cl /EHsc test1.cpp<br>#include &lt;vector&gt;<br>#include &lt;iostream&gt;<br>using namespace std;</p>
<p>void myInvalidParameterHandler(const wchar_t* expression,<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; const wchar_t* function, <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; const wchar_t* file, <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; unsigned int line, <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; uintptr_t pReserved)<br>{<br>&nbsp;&nbsp;&nbsp; cout &lt;&lt; "just ignore it" &lt;&lt; endl;<br>}</p>
<p>int main()<br>{<br>&nbsp;&nbsp;&nbsp; vector&lt;int&gt; v;<br>&nbsp;&nbsp;&nbsp; v.push_back(11);<br>&nbsp;&nbsp;&nbsp; v.push_back(22);</p>
<p>&nbsp;&nbsp;&nbsp; cout &lt;&lt; v[1] &lt;&lt; endl;</p>
<p>&nbsp;&nbsp;&nbsp; _set_invalid_parameter_handler(myInvalidParameterHandler);</p>
<p>&nbsp;&nbsp;&nbsp; cout &lt;&lt; v[2] &lt;&lt; endl;&nbsp;&nbsp; // out of range!</p>
<p>&nbsp;&nbsp;&nbsp; return 0;<br>}</p>
<p>--------------------------------------------------------------------------------</p>
<p>程序运行结果：<br>22<br>just ignore it<br>131074</p>
<p>&nbsp;&nbsp;&nbsp; 另外，如果定义_SECURE_SCL_THROWS为1，则在Debug版程序中需要在捕获异常之前先调用 _CrtSetReportMode(_CRT_ASSERT, 0)禁用ASSERT报错，并在捕获异常之后恢复。因为在程序抛出异常之前会先触发断言失败。示例代码如下：</p>
<p><br>--------------------------------------------------------------------------------<br>// cl /EHsc /D_DEBUG /MDd test2.cpp<br>#define _SECURE_SCL_THROWS 1</p>
<p>#include &lt;vector&gt;<br>#include &lt;iostream&gt;<br>#include &lt;crtdbg.h&gt;&nbsp; // For _CrtSetReportMode</p>
<p>using namespace std;</p>
<p><br>int main()<br>{<br>&nbsp;&nbsp;&nbsp; vector&lt;int&gt; v;<br>&nbsp;&nbsp;&nbsp; v.push_back(11);<br>&nbsp;&nbsp;&nbsp; v.push_back(22);</p>
<p>&nbsp;&nbsp;&nbsp; cout &lt;&lt; v[1] &lt;&lt; endl;</p>
<p>&nbsp;&nbsp;&nbsp; // disable ASSERT<br>&nbsp;&nbsp;&nbsp; int saved = _CrtSetReportMode(_CRT_ASSERT, 0);</p>
<p>&nbsp;&nbsp;&nbsp; try {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cout &lt;&lt; v[2] &lt;&lt; endl;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // out of range<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; catch (std::out_of_range &amp;) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cout &lt;&lt; "out of range" &lt;&lt; endl;<br>&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp; // restore ASSERT<br>&nbsp;&nbsp;&nbsp; _CrtSetReportMode(_CRT_ASSERT, saved);</p>
<p>&nbsp;&nbsp;&nbsp; return 0;<br>}</p>
<p>--------------------------------------------------------------------------------</p>
<p>程序运行结果：<br>22<br>out of range</p>
<p><br>--------------------------------------------------------------------------------<br>Part Two 库</p>
<p>迭代器与容器</p>
<p>&nbsp;&nbsp;&nbsp; 如果宏_SECURE_SCL为1，则所有标准库容器的迭代器都是Checked Iterator；如果宏_SECURE_SCL为0，则所有标准库容器的迭代器都是Unchecked Iterator。</p>
<p>&nbsp;&nbsp;&nbsp; 数组、指针及自定义迭代器类型均是Uncheck Iterator，但可以通过迭代器适配器stdext::checked_array_iterator和 stdext::checked_iterator把它们适配为Checked Iterator（注：VC对C++的所有扩展名字都位于名字空间stdext中）。例如，下面的代码片断使用 checked_array_iterator把一个数组（也可以是指针）适配为一个Checked Iterator：</p>
<p>// 示例代码片断<br>int a[]={1, 2, 3, 4, 5, 6};<br>int b[6];<br>copy(a, a + 6, stdext::checked_array_iterator&lt;int*&gt;(b, 5));</p>
<p>&nbsp;&nbsp;&nbsp; 如果宏_SECURE_SCL为1，则下面这些容器成员函数均会进行越界检查（Checked Iterator功能）：<br>&nbsp;&nbsp;&nbsp; basic_string::operator[]、 bitset::operator[]、deque::back、deque::front、deque::operator[]、 list::back、list::front、queue::back、queue::front、valarray::operator[]、 vector::back、vector::front、vector::operator[]。</p>
<p>算法</p>
<p>&nbsp;&nbsp;&nbsp; VC对C++标准库中部分算法进行了扩展。所有扩展算法均有一个对应的标准算法，且都位于名字空间stdext中，所在头文件与对应的标准算法相同，参数与用法也一样，唯一的区别是对参数迭代器的要求有所不同。这些扩展算法有两个版本，一个checked版本和一个unchecked版本，其函数名就是在标准算法的函数名之前添加前缀checked_和unchecked_。例如，标准算法std::copy有两个对应的扩展算法：stdext::check_copy和stdext::unchecked_copy。</p>
<p>当_SECURE_SCL为1时，<br>&nbsp;&nbsp;&nbsp; 如果标准算法有扩展版本，则此时标准算法相当于扩展算法的checked版本。<br>&nbsp;&nbsp;&nbsp; 如果作为算法参数的输出迭代器是一个Checked Iterator，那么在调用标准算法、checked版扩展算法和unchecked版扩展算法时，都将进行越界检查（例如，std::copy、 stdext::checked_copy和stdext::unchecked_copy）。<br>&nbsp;&nbsp;&nbsp; 如果作为算法参数的输出迭代器是一个Unchecked Iterator，那么在调用标准算法和checked版算法时，将产生编译警告（C4996）；而在调用unchecked版算法时不会产生警告信息。此时，都不会进行越界检查。</p>
<p>当_SECURE_SCL为0时，<br>&nbsp;&nbsp;&nbsp; 如果标准算法有扩展版本，则此时标准算法相当于扩展算法的unchecked版本。<br>&nbsp;&nbsp;&nbsp; 如果作为算法参数的输出迭代器是一个Checked Iterator，那么在调用标准算法、checked版扩展算法和unchecked版扩展算法时，都将进行越界检查。<br>&nbsp;&nbsp;&nbsp; 如果作为算法参数的输出迭代器是一个Unchecked Iterator，那么在调用checked版算法时，将产生编译警告（C4996）；而在调用标准算法和unchecked版本算法时不会产生警告信息。此时，都不会进行越界检查。</p>
<p>&nbsp;&nbsp;&nbsp; VC的扩展算法有（注：这里只列举checked版，unchecked版与checked版一一对应，只需要把函数名前缀checked_改为unchecked_即可）：<br>&nbsp;&nbsp;&nbsp; checked_adjacent_difference、checked_copy、checked_copy_backward、 checked_fill_n、checked_generate_n、checked_merge、checked_partial_sum、 checked_remove_copy、checked_remove_copy_if、checked_replace_copy、 checked_replace_copy_if、checked_reverse_copy、checked_rotate_copy、 checked_set_difference、checked_set_intersection、 checked_set_symmetric_difference、checked_set_union、 checked_uninitialized_copy、checked_uninitialized_fill_n、 checked_unique_copy。</p>
<p>&nbsp;</p>
<p>--------------------------------------------------------------------------------<br>其它编译问题</p>
<p>&nbsp;&nbsp;&nbsp; 请尝试编译如下代码（注意使用下面提供的编译选项！）：</p>
<p><br>--------------------------------------------------------------------------------<br>// 示例代码<br>// cl /EHsc /D_DEBUG /MDd /Za test.cpp<br>#define _SECURE_SCL_THROWS 1</p>
<p>#include &lt;string&gt;</p>
<p>int main()<br>{<br>&nbsp;&nbsp;&nbsp; return 0;<br>}</p>
<p>--------------------------------------------------------------------------------</p>
<p>我的VC9 SP1报错如下：</p>
<p>--------------------------------------------------------------------------------<br>test.cpp<br>D:\Microsoft Visual Studio 9.0\VC\INCLUDE\xstring(1566) : error C3861: &#8220;_Xran&#8221;<br>: 找不到标识符<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; D:\Microsoft Visual Studio 9.0\VC\INCLUDE\xstring(1557): 编译类 模板 成<br>员函数&#8220;char &amp;std::basic_string&lt;_Elem,_Traits,_Ax&gt;::operator [](unsigned int)&#8221;<br>时<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; with<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; _Elem=char,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; _Traits=std::char_traits&lt;char&gt;,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; _Ax=std::allocator&lt;char&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ]<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; D:\Microsoft Visual Studio 9.0\VC\INCLUDE\xstring(2221): 参见对正在编译<br>的类 模板 实例化&#8220;std::basic_string&lt;_Elem,_Traits,_Ax&gt;&#8221;的引用<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; with<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; _Elem=char,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; _Traits=std::char_traits&lt;char&gt;,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; _Ax=std::allocator&lt;char&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ]</p>
<p>--------------------------------------------------------------------------------</p>
<p>&nbsp;&nbsp;&nbsp; 看到上面的源代码和报错信息，估计有人会发疯了（我无意中挖掘出这个编译场景，抓狂了半天！）。确实，代码本身是没有任意问题的（根本就没有一行自己的代码嘛），那只可能出在编译器或者编译选项身上。由于我这里给出的是命令行选项，很容易发现问题所在。我当时遇到这个场景是在一个IDE环境中，费了好大的劲才从一堆选项中把元凶揪出来:-P<br>&nbsp; <br>&nbsp;&nbsp;&nbsp; 其实，这堆错误信息是由编译选项/Za引起的。/Za选项表示禁用编译器扩展，而我们这里讨论的Checked Iterator刚好就是编译器扩展功能，so&#8230;&#8230;over<br>文章出处：<a href="http://www.diybl.com/course/3_program/vc/vc_js/2008829/138422.html">http://www.diybl.com/course/3_program/vc/vc_js/2008829/138422.html</a></p><img src ="http://www.cppblog.com/windeer/aggbug/78249.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/windeer/" target="_blank">alpha</a> 2009-03-29 12:08 <a href="http://www.cppblog.com/windeer/articles/78249.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>