﻿<?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++博客-welcome-随笔分类-C++ STL</title><link>http://www.cppblog.com/stdyh/category/1990.html</link><description>vc java sdk</description><language>zh-cn</language><lastBuildDate>Sun, 16 Dec 2012 06:44:57 GMT</lastBuildDate><pubDate>Sun, 16 Dec 2012 06:44:57 GMT</pubDate><ttl>60</ttl><item><title>C++异常总结</title><link>http://www.cppblog.com/stdyh/archive/2012/11/30/195828.html</link><dc:creator>dyh</dc:creator><author>dyh</author><pubDate>Fri, 30 Nov 2012 07:58:00 GMT</pubDate><guid>http://www.cppblog.com/stdyh/archive/2012/11/30/195828.html</guid><wfw:comment>http://www.cppblog.com/stdyh/comments/195828.html</wfw:comment><comments>http://www.cppblog.com/stdyh/archive/2012/11/30/195828.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/stdyh/comments/commentRss/195828.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/stdyh/services/trackbacks/195828.html</trackback:ping><description><![CDATA[<div>1. 抛出的异常对象不应该是指针类型</div><div>因为指针指向的对象的删除和析构由谁来处理，什么时候执行，都是无法确定的事情，C++也没有定义，比如堆和栈上的对象的处理方式必然不一样<br /></div><div></div><div>2. 不能显式地把NULL作为异常对象抛出</div><div>因为throw(NULL)=tbrow(0)，因此NULL会被当作整型捕获，而不是空指针常量，这可能与程序员的预期不一致<br /></div><div></div><div>3. 如果一个函数声明时指定了具体的异常类型，那么它只能抛出指定类型的异常</div><div>函数的代码结构如下：返回值类型函数名(形参表)throw(类型名表){函数体}</div><div>int A() throw(myexception, int) &nbsp;-- 只能抛出myexception和int两种类型的异常</div><div>int A() throw() &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;-- 不抛出任何异常</div><div>int A() &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;-- 可以抛出任何异常，也可以不抛出异常</div><div></div><div>函数原型中的异常声明要与实现中的异常声明一致，否则会引起异常冲突。由于异常机制是在运行出现异常时才发挥作用的，因此如果函数的实现中抛出了没有在其异常声明列表中列出的异常，编译器也许不能检查出来。当抛出一个未在其异常声明列表里的异常类型时，unexpected()函数会被调用，默认会导致std::bad_exception类型的异常被抛出。如果std::bad_exception不在异常声明列表里，又会导致terminate()被调用，从而导致程序结束<br /></div><div></div><div>4. 异常只能在初始化之后而且程序结束之前抛出<br /></div><div></div><div>5. throw语句中的表达式本身不能引发新的异常<br /></div><div></div><div>6. 空的throw语句只能出现在catch语句块中</div><div>空的throw用来将捕获的异常再抛出，可以实现多个处理程序问异常的传递。然而，如果在catch语句外用，由于没有捕获到异常，也就没有东西可以再抛出，这样会导致程序以不定的方式终止(这依赖具体的编译器)<br /></div><div></div><div>7. 典型的try-catch结构应该是派生派在最前面，基类在后，最后是...<br /></div><div></div><div>8. catch的处理顺序为从上到下，只要找到一个匹配的异常类型，后面的异常处理都被忽略<br /></div><div></div><div>9. 若异常对象为类的对象时，应该通过引用来捕获</div><div>若不是用引用，则派生类对象总是会被截断成为基类对象</div><div></div><img src ="http://www.cppblog.com/stdyh/aggbug/195828.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/stdyh/" target="_blank">dyh</a> 2012-11-30 15:58 <a href="http://www.cppblog.com/stdyh/archive/2012/11/30/195828.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]用两个栈实现一个队列——我作为面试官的小结</title><link>http://www.cppblog.com/stdyh/archive/2012/11/16/195273.html</link><dc:creator>dyh</dc:creator><author>dyh</author><pubDate>Fri, 16 Nov 2012 08:12:00 GMT</pubDate><guid>http://www.cppblog.com/stdyh/archive/2012/11/16/195273.html</guid><wfw:comment>http://www.cppblog.com/stdyh/comments/195273.html</wfw:comment><comments>http://www.cppblog.com/stdyh/archive/2012/11/16/195273.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/stdyh/comments/commentRss/195273.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/stdyh/services/trackbacks/195273.html</trackback:ping><description><![CDATA[From:&nbsp;http://www.cnblogs.com/wanghui9072229/archive/2011/11/22/2259391.html<br /><br /><p style=" padding: 0px; font-size: 13px; line-height: 19px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; background-color: #fefef2;"><span style="margin: 0px; padding: 0px; line-height: 1.5; font-family: 宋体;">两年前从网上看到一道面试题：用两个栈（</span><span style="margin: 0px; padding: 0px; line-height: 1.5;">Stack</span><span style="margin: 0px; padding: 0px; line-height: 1.5; font-family: 宋体;">）实现一个队列（</span><span style="margin: 0px; padding: 0px; line-height: 1.5;">Queue</span><span style="margin: 0px; padding: 0px; line-height: 1.5; font-family: 宋体;">）。觉得不错，就经常拿来面试，几年下来，做此题的应该有几十人了。通过对面试者的表现和反应，有一些统计和感受，在此做个小结。</span></p><p style=" padding: 0px; font-size: 13px; line-height: 19px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; background-color: #fefef2;">&nbsp;</p><p style=" padding: 0px; font-size: 13px; line-height: 19px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; background-color: #fefef2;"><span style="margin: 0px; padding: 0px; line-height: 1.5; font-family: 宋体;">用</span><span style="margin: 0px; padding: 0px; line-height: 1.5;">C++</span><span style="margin: 0px; padding: 0px; line-height: 1.5; font-family: 宋体;">描述，题目大致是这样的：</span></p><p style=" padding: 0px; font-size: 13px; line-height: 19px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; background-color: #fefef2;">&nbsp;</p><p style=" padding: 0px; font-size: 13px; line-height: 19px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; background-color: #fefef2;"><span style="margin: 0px; padding: 0px; line-height: 1.5; font-family: 宋体;">已知下面</span><span style="margin: 0px; padding: 0px; line-height: 1.5;">Stack</span><span style="margin: 0px; padding: 0px; line-height: 1.5; font-family: 宋体;">类及其</span><span style="margin: 0px; padding: 0px; line-height: 1.5;">3</span><span style="margin: 0px; padding: 0px; line-height: 1.5; font-family: 宋体;">个方法</span><span style="margin: 0px; padding: 0px; line-height: 1.5;">Push</span><span style="margin: 0px; padding: 0px; line-height: 1.5; font-family: 宋体;">、</span><span style="margin: 0px; padding: 0px; line-height: 1.5;">Pop</span><span style="margin: 0px; padding: 0px; line-height: 1.5; font-family: 宋体;">和</span><span style="margin: 0px; padding: 0px; line-height: 1.5;">&nbsp;Count</span><span style="margin: 0px; padding: 0px; line-height: 1.5; font-family: 宋体;">，请用</span><span style="margin: 0px; padding: 0px; line-height: 1.5;">2</span><span style="margin: 0px; padding: 0px; line-height: 1.5; font-family: 宋体;">个</span><span style="margin: 0px; padding: 0px; line-height: 1.5;">Stack</span><span style="margin: 0px; padding: 0px; line-height: 1.5; font-family: 宋体;">实现</span><span style="margin: 0px; padding: 0px; line-height: 1.5;">Queue</span><span style="margin: 0px; padding: 0px; line-height: 1.5; font-family: 宋体;">类的入队</span><span style="margin: 0px; padding: 0px; line-height: 1.5;">(Enqueue)</span><span style="margin: 0px; padding: 0px; line-height: 1.5; font-family: 宋体;">出队</span><span style="margin: 0px; padding: 0px; line-height: 1.5;">(Dequeue)</span><span style="margin: 0px; padding: 0px; line-height: 1.5; font-family: 宋体;">方法。</span></p><p style=" padding: 0px; font-size: 13px; line-height: 19px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; background-color: #fefef2;">&nbsp;</p><p style=" padding: 0px; font-size: 13px; line-height: 19px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; background-color: #fefef2;"><span style="margin: 0px; padding: 0px; line-height: 1.5;">class Stack</span></p><p style=" padding: 0px; font-size: 13px; line-height: 19px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; background-color: #fefef2;"><span style="margin: 0px; padding: 0px; line-height: 1.5;">{</span></p><p style=" padding: 0px; font-size: 13px; line-height: 19px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; background-color: #fefef2;"><span style="margin: 0px; padding: 0px; line-height: 1.5;">&#8230;</span></p><p style=" padding: 0px; font-size: 13px; line-height: 19px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; background-color: #fefef2;"><span style="margin: 0px; padding: 0px; line-height: 1.5;">public:</span></p><p style=" padding: 0px; font-size: 13px; line-height: 19px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; background-color: #fefef2;"><span style="margin: 0px; padding: 0px; line-height: 1.5;"><span style="margin: 0px; padding: 0px; line-height: 1.5;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>void Push(int x); // Push an element in stack;</span></p><p style=" padding: 0px; font-size: 13px; line-height: 19px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; background-color: #fefef2;"><span style="margin: 0px; padding: 0px; line-height: 1.5;"><span style="margin: 0px; padding: 0px; line-height: 1.5;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>int Pop();<span style="margin: 0px; padding: 0px; line-height: 1.5;">&nbsp;&nbsp;</span>// Pop an element out of stack;</span></p><p style=" padding: 0px; font-size: 13px; line-height: 19px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; background-color: #fefef2;"><span style="margin: 0px; padding: 0px; line-height: 1.5;"><span style="margin: 0px; padding: 0px; line-height: 1.5;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>int Count() const;<span style="margin: 0px; padding: 0px; line-height: 1.5;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>// Return the number of the elements in stack;</span></p><p style=" padding: 0px; font-size: 13px; line-height: 19px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; background-color: #fefef2;"><span style="margin: 0px; padding: 0px; line-height: 1.5;">&#8230;</span></p><p style=" padding: 0px; font-size: 13px; line-height: 19px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; background-color: #fefef2;"><span style="margin: 0px; padding: 0px; line-height: 1.5;">};</span></p><p style=" padding: 0px; font-size: 13px; line-height: 19px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; background-color: #fefef2;">&nbsp;</p><p style=" padding: 0px; font-size: 13px; line-height: 19px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; background-color: #fefef2;"><span style="margin: 0px; padding: 0px; line-height: 1.5;">class Queue</span></p><p style=" padding: 0px; font-size: 13px; line-height: 19px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; background-color: #fefef2;"><span style="margin: 0px; padding: 0px; line-height: 1.5;">{</span></p><p style=" padding: 0px; font-size: 13px; line-height: 19px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; background-color: #fefef2;"><span style="margin: 0px; padding: 0px; line-height: 1.5;">&#8230;</span></p><p style=" padding: 0px; font-size: 13px; line-height: 19px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; background-color: #fefef2;"><span style="margin: 0px; padding: 0px; line-height: 1.5;">public:</span></p><p style=" padding: 0px; font-size: 13px; line-height: 19px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; background-color: #fefef2;"><span style="margin: 0px; padding: 0px; line-height: 1.5;"><span style="margin: 0px; padding: 0px; line-height: 1.5;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>void Enqueue(int x);</span></p><p style=" padding: 0px; font-size: 13px; line-height: 19px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; background-color: #fefef2;"><span style="margin: 0px; padding: 0px; line-height: 1.5;"><span style="margin: 0px; padding: 0px; line-height: 1.5;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>int Dequeue();</span></p><p style=" padding: 0px; font-size: 13px; line-height: 19px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; background-color: #fefef2;">&nbsp;</p><p style=" padding: 0px; font-size: 13px; line-height: 19px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; background-color: #fefef2;"><span style="margin: 0px; padding: 0px; line-height: 1.5;">private:</span></p><p style=" padding: 0px; font-size: 13px; line-height: 19px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; background-color: #fefef2;"><span style="margin: 0px; padding: 0px; line-height: 1.5;"><span style="margin: 0px; padding: 0px; line-height: 1.5;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>Stack s1;</span></p><p style=" padding: 0px; font-size: 13px; line-height: 19px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; background-color: #fefef2;"><span style="margin: 0px; padding: 0px; line-height: 1.5;"><span style="margin: 0px; padding: 0px; line-height: 1.5;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>Stack s2;</span></p><p style=" padding: 0px; font-size: 13px; line-height: 19px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; background-color: #fefef2;"><span style="margin: 0px; padding: 0px; line-height: 1.5;">&#8230;</span></p><p style=" padding: 0px; font-size: 13px; line-height: 19px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; background-color: #fefef2;"><span style="margin: 0px; padding: 0px; line-height: 1.5;">};</span></p><p style=" padding: 0px; font-size: 13px; line-height: 19px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; background-color: #fefef2;">&nbsp;</p><p style=" padding: 0px; font-size: 13px; line-height: 19px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; background-color: #fefef2;"><span style="margin: 0px; padding: 0px; line-height: 1.5; font-family: 宋体;">这道题应该不算难，比起《编程之美》中微软那些什么&#8220;翻烙饼&#8221;的面试题，难度上差远了。况且，由于时间关系，我一般也不要求面试者写代码，只描述清楚思路即可。出这道题，主要考察</span><span style="margin: 0px; padding: 0px; line-height: 1.5;">3</span><span style="margin: 0px; padding: 0px; line-height: 1.5; font-family: 宋体;">点：</span></p><p style=" padding: 0px; font-size: 13px; line-height: 19px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; background-color: #fefef2;">&nbsp;</p><p style="margin: 0cm 0cm 0pt 18pt; padding: 0px; text-indent: -18pt; line-height: 19px; font-size: 13px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; background-color: #fefef2;"><span style="margin: 0px; padding: 0px; line-height: 1.5;"><span style="margin: 0px; padding: 0px; line-height: 1.5;">1.<span style="margin: 0px; padding: 0px; line-height: normal; font-size: 7pt; font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span></span><span style="margin: 0px; padding: 0px; line-height: 1.5; font-family: 宋体;">在短时间内，能不能找到解决这道题的足够清晰的思路（思维是否敏捷、清晰）。</span></p><p style="margin: 0cm 0cm 0pt 18pt; padding: 0px; text-indent: -18pt; line-height: 19px; font-size: 13px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; background-color: #fefef2;"><span style="margin: 0px; padding: 0px; line-height: 1.5;"><span style="margin: 0px; padding: 0px; line-height: 1.5;">2.<span style="margin: 0px; padding: 0px; line-height: normal; font-size: 7pt; font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span></span><span style="margin: 0px; padding: 0px; line-height: 1.5; font-family: 宋体;">能不能在单向表述中，清楚地描述自己的思路和想法（表述能力是否达到要求）。</span></p><p style="margin: 0cm 0cm 0pt 18pt; padding: 0px; text-indent: -18pt; line-height: 19px; font-size: 13px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; background-color: #fefef2;"><span style="margin: 0px; padding: 0px; line-height: 1.5;"><span style="margin: 0px; padding: 0px; line-height: 1.5;">3.<span style="margin: 0px; padding: 0px; line-height: normal; font-size: 7pt; font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span></span><span style="margin: 0px; padding: 0px; line-height: 1.5; font-family: 宋体;">对于某些具体细节，能不能考虑到（是否足够细致）。</span></p><p style=" padding: 0px; font-size: 13px; line-height: 19px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; background-color: #fefef2;">&nbsp;</p><p style=" padding: 0px; font-size: 13px; line-height: 19px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; background-color: #fefef2;"><span style="margin: 0px; padding: 0px; line-height: 1.5; font-family: 宋体;">总体上，以</span><span style="margin: 0px; padding: 0px; line-height: 1.5;">10</span><span style="margin: 0px; padding: 0px; line-height: 1.5; font-family: 宋体;">人为例，实际的结果大致是：</span></p><p style=" padding: 0px; font-size: 13px; line-height: 19px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; background-color: #fefef2;">&nbsp;</p><p style="margin: 0cm 0cm 0pt 18pt; padding: 0px; text-indent: -18pt; line-height: 19px; font-size: 13px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; background-color: #fefef2;"><span style="margin: 0px; padding: 0px; line-height: 1.5;"><span style="margin: 0px; padding: 0px; line-height: 1.5;">1.<span style="margin: 0px; padding: 0px; line-height: normal; font-size: 7pt; font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span></span><span style="margin: 0px; padding: 0px; line-height: 1.5;">8</span><span style="margin: 0px; padding: 0px; line-height: 1.5; font-family: 宋体;">个人可以找到解决答案，</span><span style="margin: 0px; padding: 0px; line-height: 1.5;">2</span><span style="margin: 0px; padding: 0px; line-height: 1.5; font-family: 宋体;">个人无法找到答案（即使进行了必要的提示，曾经有位号称美国</span><span style="margin: 0px; padding: 0px; line-height: 1.5;">MIT</span><span style="margin: 0px; padding: 0px; line-height: 1.5; font-family: 宋体;">深造</span><span style="margin: 0px; padding: 0px; line-height: 1.5;">2</span><span style="margin: 0px; padding: 0px; line-height: 1.5; font-family: 宋体;">年，之后在</span><span style="margin: 0px; padding: 0px; line-height: 1.5;">Google</span><span style="margin: 0px; padding: 0px; line-height: 1.5; font-family: 宋体;">美国公司工作过</span><span style="margin: 0px; padding: 0px; line-height: 1.5;">8</span><span style="margin: 0px; padding: 0px; line-height: 1.5; font-family: 宋体;">个月的兄弟，也没做出来）。</span></p><p style="margin: 0cm 0cm 0pt 18pt; padding: 0px; text-indent: -18pt; line-height: 19px; font-size: 13px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; background-color: #fefef2;"><span style="margin: 0px; padding: 0px; line-height: 1.5;"><span style="margin: 0px; padding: 0px; line-height: 1.5;">2.<span style="margin: 0px; padding: 0px; line-height: normal; font-size: 7pt; font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span></span><span style="margin: 0px; padding: 0px; line-height: 1.5;">8</span><span style="margin: 0px; padding: 0px; line-height: 1.5; font-family: 宋体;">个找到答案的人中，</span><span style="margin: 0px; padding: 0px; line-height: 1.5;">6</span><span style="margin: 0px; padding: 0px; line-height: 1.5; font-family: 宋体;">个找到的方法相同，</span><span style="margin: 0px; padding: 0px; line-height: 1.5;">2</span><span style="margin: 0px; padding: 0px; line-height: 1.5; font-family: 宋体;">个人找到其它变种。</span></p><p style="margin: 0cm 0cm 0pt 18pt; padding: 0px; text-indent: -18pt; line-height: 19px; font-size: 13px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; background-color: #fefef2;"><span style="margin: 0px; padding: 0px; line-height: 1.5;"><span style="margin: 0px; padding: 0px; line-height: 1.5;">3.<span style="margin: 0px; padding: 0px; line-height: normal; font-size: 7pt; font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span></span><span style="margin: 0px; padding: 0px; line-height: 1.5; font-family: 宋体;">在这</span><span style="margin: 0px; padding: 0px; line-height: 1.5;">8</span><span style="margin: 0px; padding: 0px; line-height: 1.5; font-family: 宋体;">个人中，有</span><span style="margin: 0px; padding: 0px; line-height: 1.5;">1</span><span style="margin: 0px; padding: 0px; line-height: 1.5; font-family: 宋体;">个人可以不经提示，同时想到大众方法和变种。</span></p><p style=" padding: 0px; font-size: 13px; line-height: 19px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; background-color: #fefef2;">&nbsp;</p><p style=" padding: 0px; font-size: 13px; line-height: 19px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; background-color: #fefef2;"><span style="margin: 0px; padding: 0px; line-height: 1.5; font-family: 宋体;">大多数人的思路是：始终维护</span><span style="margin: 0px; padding: 0px; line-height: 1.5;">s1</span><span style="margin: 0px; padding: 0px; line-height: 1.5; font-family: 宋体;">作为存储空间，以</span><span style="margin: 0px; padding: 0px; line-height: 1.5;">s2</span><span style="margin: 0px; padding: 0px; line-height: 1.5; font-family: 宋体;">作为临时缓冲区。</span></p><p style=" padding: 0px; font-size: 13px; line-height: 19px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; background-color: #fefef2;"><span style="margin: 0px; padding: 0px; line-height: 1.5; font-family: 宋体;">入队时，将元素压入</span><span style="margin: 0px; padding: 0px; line-height: 1.5;">s1</span><span style="margin: 0px; padding: 0px; line-height: 1.5; font-family: 宋体;">。</span></p><p style=" padding: 0px; font-size: 13px; line-height: 19px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; background-color: #fefef2;"><span style="margin: 0px; padding: 0px; line-height: 1.5; font-family: 宋体;">出队时，将</span><span style="margin: 0px; padding: 0px; line-height: 1.5;">s1</span><span style="margin: 0px; padding: 0px; line-height: 1.5; font-family: 宋体;">的元素逐个&#8220;倒入&#8221;（弹出并压入）</span><span style="margin: 0px; padding: 0px; line-height: 1.5;">s2</span><span style="margin: 0px; padding: 0px; line-height: 1.5; font-family: 宋体;">，将</span><span style="margin: 0px; padding: 0px; line-height: 1.5;">s2</span><span style="margin: 0px; padding: 0px; line-height: 1.5; font-family: 宋体;">的顶元素弹出作为出队元素，之后再将</span><span style="margin: 0px; padding: 0px; line-height: 1.5;">s2</span><span style="margin: 0px; padding: 0px; line-height: 1.5; font-family: 宋体;">剩下的元素逐个&#8220;倒回&#8221;</span><span style="margin: 0px; padding: 0px; line-height: 1.5;">s1</span><span style="margin: 0px; padding: 0px; line-height: 1.5; font-family: 宋体;">。</span></p><p style=" padding: 0px; font-size: 13px; line-height: 19px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; background-color: #fefef2;"><span style="margin: 0px; padding: 0px; line-height: 1.5; font-family: 宋体;">见下面示意图：</span></p><p style=" padding: 0px; font-size: 13px; line-height: 19px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; background-color: #fefef2;">&nbsp;</p><p align="center" style=" padding: 0px; font-size: 13px; line-height: 19px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; background-color: #fefef2;"><a href="http://images.cnblogs.com/cnblogs_com/wanghui9072229/201111/20111122200217730.jpg" style="margin: 0px; padding: 0px; color: #075db3;"><img title="2Stacks1Queue" border="0" alt="2Stacks1Queue" src="http://images.cnblogs.com/cnblogs_com/wanghui9072229/201111/201111222002191928.jpg" width="640" height="233" style="margin: 0px; padding: 0px; border: 0px; background-image: none; display: inline;" /></a></p><p style=" padding: 0px; font-size: 13px; line-height: 19px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; background-color: #fefef2;">&nbsp;</p><p style=" padding: 0px; font-size: 13px; line-height: 19px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; background-color: #fefef2;"><span style="margin: 0px; padding: 0px; line-height: 1.5; font-family: 宋体;">上述思路，可行性毋庸置疑。但有一个细节是可以优化一下的。即：在出队时，将</span><span style="margin: 0px; padding: 0px; line-height: 1.5;">s1</span><span style="margin: 0px; padding: 0px; line-height: 1.5; font-family: 宋体;">的元素逐个&#8220;倒入&#8221;</span><span style="margin: 0px; padding: 0px; line-height: 1.5;">s2</span><span style="margin: 0px; padding: 0px; line-height: 1.5; font-family: 宋体;">时，原在</span><span style="margin: 0px; padding: 0px; line-height: 1.5;">s1</span><span style="margin: 0px; padding: 0px; line-height: 1.5; font-family: 宋体;">栈底的元素，不用&#8220;倒入&#8221;</span><span style="margin: 0px; padding: 0px; line-height: 1.5;">s2</span><span style="margin: 0px; padding: 0px; line-height: 1.5; font-family: 宋体;">（即只&#8220;倒&#8221;</span><span style="margin: 0px; padding: 0px; line-height: 1.5;">s1.Count()-1</span><span style="margin: 0px; padding: 0px; line-height: 1.5; font-family: 宋体;">个），可直接弹出作为出队元素返回。这样可以减少一次压栈的操作。约有一半人，经提示后能意识到此问题。</span></p><p style=" padding: 0px; font-size: 13px; line-height: 19px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; background-color: #fefef2;">&nbsp;</p><p style=" padding: 0px; font-size: 13px; line-height: 19px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; background-color: #fefef2;"><span style="margin: 0px; padding: 0px; line-height: 1.5; font-family: 宋体;">上述思路，有些变种，如：</span></p><p style=" padding: 0px; font-size: 13px; line-height: 19px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; background-color: #fefef2;"><span style="margin: 0px; padding: 0px; line-height: 1.5; font-family: 宋体;">入队时，先判断</span><span style="margin: 0px; padding: 0px; line-height: 1.5;">s1</span><span style="margin: 0px; padding: 0px; line-height: 1.5; font-family: 宋体;">是否为空，如不为空，说明所有元素都在</span><span style="margin: 0px; padding: 0px; line-height: 1.5;">s1</span><span style="margin: 0px; padding: 0px; line-height: 1.5; font-family: 宋体;">，此时将入队元素直接压入</span><span style="margin: 0px; padding: 0px; line-height: 1.5;">s1</span><span style="margin: 0px; padding: 0px; line-height: 1.5; font-family: 宋体;">；如为空，要将</span><span style="margin: 0px; padding: 0px; line-height: 1.5;">s2</span><span style="margin: 0px; padding: 0px; line-height: 1.5; font-family: 宋体;">的元素逐个&#8220;倒回&#8221;</span><span style="margin: 0px; padding: 0px; line-height: 1.5;">s1</span><span style="margin: 0px; padding: 0px; line-height: 1.5; font-family: 宋体;">，再压入入队元素。</span></p><p style=" padding: 0px; font-size: 13px; line-height: 19px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; background-color: #fefef2;"><span style="margin: 0px; padding: 0px; line-height: 1.5; font-family: 宋体;">出队时，先判断</span><span style="margin: 0px; padding: 0px; line-height: 1.5;">s2</span><span style="margin: 0px; padding: 0px; line-height: 1.5; font-family: 宋体;">是否为空，如不为空，直接弹出</span><span style="margin: 0px; padding: 0px; line-height: 1.5;">s2</span><span style="margin: 0px; padding: 0px; line-height: 1.5; font-family: 宋体;">的顶元素并出队；如为空，将</span><span style="margin: 0px; padding: 0px; line-height: 1.5;">s1</span><span style="margin: 0px; padding: 0px; line-height: 1.5; font-family: 宋体;">的元素逐个&#8220;倒入&#8221;</span><span style="margin: 0px; padding: 0px; line-height: 1.5;">s2</span><span style="margin: 0px; padding: 0px; line-height: 1.5; font-family: 宋体;">，把最后一个元素弹出并出队。</span></p><p style=" padding: 0px; font-size: 13px; line-height: 19px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; background-color: #fefef2;"><span style="margin: 0px; padding: 0px; line-height: 1.5; font-family: 宋体;">有些人能同时想到大众方法和变种，应该说头脑还是比较灵光的。</span></p><p style=" padding: 0px; font-size: 13px; line-height: 19px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; background-color: #fefef2;">&nbsp;</p><p style=" padding: 0px; font-size: 13px; line-height: 19px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; background-color: #fefef2;"><span style="margin: 0px; padding: 0px; line-height: 1.5; font-family: 宋体;">相对于第一种方法，变种的</span><span style="margin: 0px; padding: 0px; line-height: 1.5;">s2</span><span style="margin: 0px; padding: 0px; line-height: 1.5; font-family: 宋体;">好像比较&#8220;懒&#8221;，每次出队后，并不将元素&#8220;倒回&#8221;</span><span style="margin: 0px; padding: 0px; line-height: 1.5;">s1</span><span style="margin: 0px; padding: 0px; line-height: 1.5; font-family: 宋体;">，如果赶上下次还是出队操作，效率会高一些，但下次如果是入队操作，效率不如第一种方法。我有时会让面试者分析比较不同方法的性能。我感觉（没做深入研究），入队、出队操作随机分布时，上述两种方法总体上时间复杂度和空间复杂度应该相差无几（无非多个少个判断）。</span></p><p style=" padding: 0px; font-size: 13px; line-height: 19px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; background-color: #fefef2;">&nbsp;</p><p style=" padding: 0px; font-size: 13px; line-height: 19px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; background-color: #fefef2;"><span style="margin: 0px; padding: 0px; line-height: 1.5; font-family: 宋体;">真正性能较高的，其实是另一个变种。即：</span></p><p style=" padding: 0px; font-size: 13px; line-height: 19px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; background-color: #fefef2;"><span style="margin: 0px; padding: 0px; line-height: 1.5; font-family: 宋体;">入队时，将元素压入</span><span style="margin: 0px; padding: 0px; line-height: 1.5;">s1</span><span style="margin: 0px; padding: 0px; line-height: 1.5; font-family: 宋体;">。</span></p><p style=" padding: 0px; font-size: 13px; line-height: 19px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; background-color: #fefef2;"><span style="margin: 0px; padding: 0px; line-height: 1.5; font-family: 宋体;">出队时，判断</span><span style="margin: 0px; padding: 0px; line-height: 1.5;">s2</span><span style="margin: 0px; padding: 0px; line-height: 1.5; font-family: 宋体;">是否为空，如不为空，则直接弹出顶元素；如为空，则将</span><span style="margin: 0px; padding: 0px; line-height: 1.5;">s1</span><span style="margin: 0px; padding: 0px; line-height: 1.5; font-family: 宋体;">的元素逐个&#8220;倒入&#8221;</span><span style="margin: 0px; padding: 0px; line-height: 1.5;">s2</span><span style="margin: 0px; padding: 0px; line-height: 1.5; font-family: 宋体;">，把最后一个元素弹出并出队。</span></p><p style=" padding: 0px; font-size: 13px; line-height: 19px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; background-color: #fefef2;"><span style="margin: 0px; padding: 0px; line-height: 1.5; font-family: 宋体;">这个思路，避免了反复&#8220;倒&#8221;栈，仅在需要时才&#8220;倒&#8221;一次。但在实际面试中很少有人说出，可能是时间较少的缘故吧。</span></p><p style=" padding: 0px; font-size: 13px; line-height: 19px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; background-color: #fefef2;">&nbsp;</p><p style=" padding: 0px; font-size: 13px; line-height: 19px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; background-color: #fefef2;"><span style="margin: 0px; padding: 0px; line-height: 1.5; font-family: 宋体;">以上几个思路乍看没什么问题了，但其实还是有个细节要考虑的。其实无论什么方法和情况，都要考虑没有元素可供出队时的处理（</span><span style="margin: 0px; padding: 0px; line-height: 1.5;">2</span><span style="margin: 0px; padding: 0px; line-height: 1.5; font-family: 宋体;">个栈都为空的时候，出队操作一定会引起异常）。在实际写代码时，忽略这些判断或异常处理，程序会出现问题。所以，能不能考虑到这些细节，也体现了个人的素养。</span></p><p style=" padding: 0px; font-size: 13px; line-height: 19px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; background-color: #fefef2;">&nbsp;</p><p style=" padding: 0px; font-size: 13px; line-height: 19px; font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; background-color: #fefef2;"><span style="margin: 0px; padding: 0px; line-height: 1.5; font-family: 宋体;">个人感觉，这道题确实有助于我鉴别应聘的人。但对于面试，毕竟还是要看面试者的综合素质，一道（或几道）题定生死不可取。</span></p><img src ="http://www.cppblog.com/stdyh/aggbug/195273.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/stdyh/" target="_blank">dyh</a> 2012-11-16 16:12 <a href="http://www.cppblog.com/stdyh/archive/2012/11/16/195273.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++ Fragment</title><link>http://www.cppblog.com/stdyh/archive/2012/11/05/194562.html</link><dc:creator>dyh</dc:creator><author>dyh</author><pubDate>Mon, 05 Nov 2012 08:37:00 GMT</pubDate><guid>http://www.cppblog.com/stdyh/archive/2012/11/05/194562.html</guid><wfw:comment>http://www.cppblog.com/stdyh/comments/194562.html</wfw:comment><comments>http://www.cppblog.com/stdyh/archive/2012/11/05/194562.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/stdyh/comments/commentRss/194562.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/stdyh/services/trackbacks/194562.html</trackback:ping><description><![CDATA[好长一段时间没有用C++写程序了，记录下C++编程的一些常用的方法，以免再次忘记：<br />1. 模板类的定义和实现必须放在同一个头文件中<br /><br />2.&nbsp;unary_function和binary_function是stl提供的一元和二元函数对象基类，子类需实现()操作符，这样的子类可以用在stl算法函数中，如sort, partition等。<div>&nbsp; &nbsp;一元函数对象例子如下：</div><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->template&nbsp;&lt;typename&nbsp;T&gt;&nbsp;<br /><span style="color: #0000FF; ">class</span>&nbsp;FilterCriterion&nbsp;:&nbsp;<span style="color: #0000FF; ">public</span>&nbsp;unary_function&lt;T,&nbsp;<span style="color: #0000FF; ">bool</span>&gt;<br />{<br /><br /><span style="color: #0000FF; ">public</span>:<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">bool</span>&nbsp;<span style="color: #0000FF; ">operator</span>()(<span style="color: #0000FF; ">const</span>&nbsp;T&amp;&nbsp;val)&nbsp;<span style="color: #0000FF; ">const</span><br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;(val.size()&nbsp;&gt;&nbsp;0);<br />&nbsp;&nbsp;&nbsp;&nbsp;};<br /><br />};<br /><br />FilterCriterion&lt;MyType&gt;&nbsp;f;<br />partition(vec.begin(),&nbsp;vec.end(),&nbsp;f); //对MyType对象进行分类（size必须&gt;0)</div><div>&nbsp; &nbsp;二元函数对象例子如下：</div><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><div style="font-size: 14px; ">template &lt;class T&gt;&nbsp;</div><div style="font-size: 14px; ">class RankCriterion : public binary_function&lt;T, T, bool&gt;</div><div style="font-size: 14px; ">{</div><div style="font-size: 14px; ">public:</div><div style="font-size: 14px; "><span style="white-space: pre; ">	</span>bool operator()(const T&amp; lhs, const T&amp; rhs) const</div><div style="font-size: 14px; "><span style="white-space: pre; ">	</span>{</div><div style="font-size: 14px; "><span style="white-space: pre; ">		return (lhs.size() &gt; rhs.size());</span></div><div style="font-size: 14px; "><span style="white-space: pre; ">	</span>};</div><div>}<br />RankCriterion&lt;MyType&gt;&nbsp;r;<br />sort(vec.begin(), vec.begin(), vec.end(),&nbsp;r); // 对MyType对象进行排序(按size大小排序）</div><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--></div>3. C++处理表达式可以采用先转成逆波兰表达式，然后计算<br /><a href="http://www.cnblogs.com/adamxx/archive/2006/08/30/703267.html">http://www.cnblogs.com/adamxx/archive/2006/08/30/703267.html</a><br /><br />4. Dll导出类或函数<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->#ifdef&nbsp;SIMPLEDLL_EXPORT<br /><span style="color: #0000FF; ">#define</span>&nbsp;DLL_EXPORT&nbsp;__declspec(dllexport)<br /><span style="color: #0000FF; ">#else</span><br /><span style="color: #0000FF; ">#define</span>&nbsp;DLL_EXPORT&nbsp;__declspec(dllimport)<br /><span style="color: #0000FF; ">#endif</span></div><br />5. const 成员函数<br />const 成员函数获得的能力：可以操作常量对象，如GetName函数定义为string GetName() const; 那么Const A a; a.GetName();是能编译通过的，若GetName不定义为const，那么上述调用编译会失败<br /><br />const成员函数失去的能力：有得必有失，<span style="color: #333333; font-family: 宋体, Arial; line-height: 24px; background-color: #ffffff;">不能修改类的数据成员，不能在函数中调用其他非const的函数</span><img src ="http://www.cppblog.com/stdyh/aggbug/194562.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/stdyh/" target="_blank">dyh</a> 2012-11-05 16:37 <a href="http://www.cppblog.com/stdyh/archive/2012/11/05/194562.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]C++开源跨平台类库集</title><link>http://www.cppblog.com/stdyh/archive/2007/04/27/23064.html</link><dc:creator>dyh</dc:creator><author>dyh</author><pubDate>Fri, 27 Apr 2007 12:48:00 GMT</pubDate><guid>http://www.cppblog.com/stdyh/archive/2007/04/27/23064.html</guid><wfw:comment>http://www.cppblog.com/stdyh/comments/23064.html</wfw:comment><comments>http://www.cppblog.com/stdyh/archive/2007/04/27/23064.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/stdyh/comments/commentRss/23064.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/stdyh/services/trackbacks/23064.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 经典的C++库<br>  STLport-------SGI STL库的跨平台可移植版本，在以前有些编译器离符合<br>        标准比较远的情况下 那时还是有用的，当然目前vc71已经比较接近标准了，<br>        故目前不怎么用它了。<br>  Boost---------准标准库， 功能强大 涉及能想的到的大部分非特别领域的算法，<br>        有一个大的C++社区支持<br>  WxWindows-----功能强大的跨平台GUI库  ，它的功能和结构都类似 MFC，故原则上<br>      可以通过WxWindows把现有MFC程序移植到非Win平台下<br>  Blitz---------高效率的数值计算函数库 ,你可以订制补充你需要的算法<br>  Log4cpp-------日志处理  ，功能类似java中的log4j<br>  ACE-----------自适应通讯环境， 重量级的通讯环境库。<br>  Crypto++ -----加/解密算法库, 非常专业的C++ 密码学函式库<br>  CppUnit  ---  一个&nbsp;&nbsp;<a href='http://www.cppblog.com/stdyh/archive/2007/04/27/23064.html'>阅读全文</a><img src ="http://www.cppblog.com/stdyh/aggbug/23064.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/stdyh/" target="_blank">dyh</a> 2007-04-27 20:48 <a href="http://www.cppblog.com/stdyh/archive/2007/04/27/23064.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>c++对象内存布局(转载)</title><link>http://www.cppblog.com/stdyh/archive/2007/01/08/17442.html</link><dc:creator>dyh</dc:creator><author>dyh</author><pubDate>Mon, 08 Jan 2007 13:17:00 GMT</pubDate><guid>http://www.cppblog.com/stdyh/archive/2007/01/08/17442.html</guid><wfw:comment>http://www.cppblog.com/stdyh/comments/17442.html</wfw:comment><comments>http://www.cppblog.com/stdyh/archive/2007/01/08/17442.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/stdyh/comments/commentRss/17442.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/stdyh/services/trackbacks/17442.html</trackback:ping><description><![CDATA[写这个文章完全是因为想要搞清楚 vc 怎么布局每个 c++ 对象,以及怎样完成指针的转换的过程.<br />　　先问一个问题,两个不同类型的指针相互转换以后,他们在数值上是一样的吗?比如:<br /><br />　　　　<font color="#000066">int nValue = 10;<br />　　　　int *pInt = &amp;nValue;<br />　　　　void *pVoid = pInt;<br />　　　　char *pChar = (char*)pInt;</font><br /><br />　　这些指针的值(不是说指针指向的内存的内容)是一样的吗? 如果你的回答是 yes,那如果是一个类的继承体系呢?在继承类向基类转换的过程中,指针的数值还是不变化的么?如果你的回答是"不一定会变化,要看类的体系是怎么设计的"的话,那恭喜你,不用看下去了.如果你还不确定究竟变还是不变,究竟哪些变,哪些不变,究竟为什么要变为什么不变的话,接着看下来.<br /><br />　　c++ 标准不规定 c++ 实现的时候的对象的具体的内存布局,除了在某些方面有小的限制以外,c++ 对象在内存里面的布局完全是由编译器自行决定,这里我也只是讨论 vc++ .net 2003 build 7.1.3091 的实现方式,我并没有在 vc5 vc6 vc.net 2002 以及其他的 2003 build 上面做过测试,结论也许不适合那些编译平台.这些属于编译器具体实现,ms 保留有在不通知你我的情况下作出更改的权利.废话这么多,马上开始.<br /><br />　　对于 c 的内建指针的转换,结果是不用多讨论的,我们只是讨论 c++ 的对象.从最简单的开始.<br /><br />　　　　<font color="#000066">class CBase<br />　　　　{<br />　　　　public:<br />　　　　　　int m_nBaseValue;<br />　　　　};</font><br /><br />　　这样的一个类在内存里放置是非常简单的,他占有4个 bytes 的空间,不用多说,我们从他派生一个类出来.<br /><br />　　　　<font color="#000066">class CDerive1 : public CBase<br />　　　　{<br />　　　　public:<br />　　　　　　int m_nDerive1Value;<br />　　　　};</font><br /><br />　　CDerive1 的对象在内存里面是怎么放的呢? 也很简单,占有8个 bytes 的空间,前4个 bytes 属于 CBase 类,后四个 bytes 属于自己.一个CDerive1 的指针转换成一个 CBase 的指针,结果是一样的.下面我们加上多重继承看看.<br /><br />　　　　<font color="#000066">class CFinal : public CDerive,public CBase <font color="#ff0000">// 这里的 CDerive 是一个和 CBase 差不多的基类</font><br />　　　　{<br />　　　　public:<br />　　　　　　int m_nFinalValue;<br />　　　　}; </font><br /><br />　　CFinal 的对象在内存里面的布局稍微复杂一点,但是也很容易想象,他占有 12 个 bytes 的空间,前4个属于 CDerive,中间4个属于 CBase,后面4个才是自己的.那一个 CFinal 的指针转换成一个 CDerive 指针,数值会变么? 转换成一个 CBase 指针呢?又会变化么?答案是,前一个不变,后一个要变化,道理非常的明显,CFinal 对象的开头刚好是一个 CDerive 对象,而 CBase 对象却在 CFinal 对象的中间,自然是要变化的了,具体怎么变化呢? 加 4 就 ok(自然要检查是否是空指针).<br /><br />　　　　<font color="#ff0000">CBase *pBase = pFinal ? (CBase*)((char*)pFinal + sizeof(CDerive)) : 0;// 当你写下 pBase = pFinal 的时候,其实是这样的</font><br /><br />　　这种不带 virtual 的继承就这么简单,只是加上一个 offset 而已.下面我们看看如果加上 virtual function 的时候是什么样子的呢?<br />还是从简单类开始.<br /><br />　　　　<font color="#000066">class CBase<br />　　　　{<br />　　　　public:<br />　　　　　　virtual void VirtualBaseFunction(){}<br />　　　　　　int m_nBaseValue;<br />　　　　}; </font><br /><br />　　这里刻意没有使用 virtual destructor,因为这个函数稍微有些不同.还是同样的问题,CBase 类在内存上占多大的空间?还是 4 bytes 么? 答案是 no, 在我的编译器上面是 8 bytes,多出来的 4 bytes 是 __vfptr(watch 窗口看见的名字),他是一个指针,指向了类的 vtable,那什么是 vtable 呢,他是用来干什么的呢? vtable 是用来支援 virtual function 机制的,他其实是一个函数指针数组(并不等同于c/c++语言里面的指针数组,因为他们的类型并不一定是一样的.)他的每一个元素都指向了一个你定义的 virtual function,这样通过一个中间层来到达动态连编的效果,这些指针是在程序运行的时候准备妥当的,而不是在编译的时候准备妥当的,这个就是动态联编的目的,具体是由谁来设置这些指针的呢?constructor/destructor/copy constructor/assignment operator他们完成的,不用奇怪,编译器会在你写的这些函数里面安插些必要的代码用来设置 vtable 的值,如果你没有写这些函数,编译器会在适当的时候帮你生成这些函数.明白一点, vtable 是用来支持 virtual function 机制的,而需要 virtual 机制的类基本上都会由一个 __vfptr 指向他自己的 vtable.在调用 virtual function的时候,编译器这样完成:<br /><br />　　　<font color="#000099">pBase-&gt;VirtualBaseFunction(); =&gt; pBase-&gt;__vfptr[0]();</font><font color="#ff0000">// 0 是你的virtual function 在 vtable 中的 slot number,编译器决定</font><br /><br />　　现在应该很想象 CBase 的大小了吧,那这个 __vfptr 是放到什么位置的呢? 在 m_nBaseValue 之前还是之后呢? 在我的编译器上看来,是在之前,为什么要放到之前,是因为在通过 指向类成员函数的指针调用 virtual function 的时候能少些代码(指汇编代码),这个原因这里就不深入讨论了,有兴趣的同学可以看看 inside the c++ object model 一书.<br />　　接下来,我们加上继承来看看.<br /><br />　　　　<font color="#000099">class CDerive1 : public CBase<br />　　　　{<br />　　　　public:<br />　　　　　　virtual void VirtualDerive1Function();<br />　　　　};</font><br /><br />　　这个时候你也许要说,内存布局跟没有 virtual 是一样的,只不过每个类多了一个 __vfptr 而已,呃...这个是不对的,在我的编译器上面 两个类共享同一个 __vfptr, vtable 里面放有两个指针,一个是两个类共享的,一个只属于 CDerive1 类,调用的时候如何呢?<br /><br />　　　<font color="#000099">pDerive1-&gt;VirtualDerive1Function() =&gt; pDerive1-&gt;__vfptr[1]();<br />　　　pDerive1-&gt;VirtualBaseFunction() =&gt; pDerive1-&gt;__vfptr[0]();</font><br /><br />　　至于指针的相互转换,数值还是没有变化的(也正是追求这种效果,所以把 __vfptr 放到类的开头,因为调整 this 指针也是要占有运行时的时间的).<br /><br />　　现在加上多重继承瞧瞧,代码我不写上来了,就跟上面的 CFinal, CDerive, CBase 体系一样,只是每个类多一个VirtualxxxFunction出来,这个时候的指针调整还是没有什么变化,所以我们只是看看 vtable 的情况,你会说 CDerive 和 CFinal 共享一个 __vfptr,而 CBase 有一个自己的 __vfptr,而 CFinal 的 __vfptr 有 2 个slot,这个结论是正确的. 同时你也会说 通过 CFinal 类调用 CBase 的函数是要进行指针调整的,yes you'r right,不仅仅是 this 指针调整(呃,this 指针会成为 function 的一个参数),还要调整 vtable 的值:<br /><br />　　　<font color="#0000cc">pFinal-&gt;VirtualBaseFunction() =&gt; (CBase*)((char*)pFinal + sizeof(CDerive))-&gt;__vfptr[0]();</font><br /><br />　　　转换成 asm 的代码大约是这样的:<br /><br /><font color="#000099">　　　mov eax,[pFinal] <font color="#ff00ff">; pFinal is a local object,pFinal will be epb - xx</font><br />　　　add eax,8 <font color="#ff00ff">; 8 = sizeof(CDerive)</font><br />　　　mov ecx,eax <font color="#ff00ff">; ecx is this pointer</font><br />　　　mov edx,[eax] <font color="#ff00ff">; edx = vtable address</font><br />　　　call [edx] <font color="#ff00ff">; call vtable[0]</font></font><br /><br />　　写到这里也就明白this指针是怎么调整的.带 virtual function 的继承也不复杂,this指针调整也是很简单的,下面看最复杂的部分 virtual inheritance.<br /><br />　　我的编译器支持虚拟继承的方式和虚函数的方式差不多,都是通过一个 table 完成,只是这个就看不到 vc 赋予的名字了,我们叫他 vbtable 吧,编译器同样在类里面加入一个指向 vbtable 的指针,我们叫他 __vbptr 吧,这个指针指向了 vbtable ,而 vbtable 里面的每一项对应了一个基类,vbtable 记录了每个基类的某一个偏移量,通过这个偏移量就能计算出具体类的指针的位置.看个简单的例子:<br /><br />　　　<font color="#000099">class CBase<br />　　　{<br />　　　public:<br />　　　　　virtual ~CBase(){}<br />　　　}; <br /><br />　　　class CMid1 : public virtual CBase<br />　　　{<br />　　　public:<br />　　　　　virtual ~CMid1(){}<br />　　　　　int m_nMid1;<br />　　　}; <br /><br />　　　class CMid2 : public virtual CBase<br />　　　{<br />　　　public:<br />　　　　　virtual ~CMid2(){}<br />　　　　　int m_nMid2;<br />　　　}; <br /><br />　　　class CFinal : public CMid1,public CMid2<br />　　　{<br />　　　public:<br />　　　　　virtual ~CFinal(){}<br />　　　　　int m_nFinal;<br />　　　}; <br /><br />　　　CFinal final;<br />　　　CFinal *pFinal = &amp;final;    <font color="#ff00ff">// pFinal = 0x0012feb4;</font><br />　　　CBase *pBase = pFinal; <font color="#ff00ff">// pBase = 0x0012fec8 = pFinal + 0x14;</font><br />　　　CMid1 *pMid1 = pFinal; <font color="#ff00ff">// pMid1 = 0x0012feb4 = pFinal;</font><br />　　　CMid2 *pMid2 = pFinal; <font color="#ff00ff">// pMid2 = 0x004210b4 = pFinal;</font></font><br /><br />　　结果让你吃惊吗? 最奇怪的地方居然是 CMid2 和 CMid1 的地址居然是一样的,这个是因为 vc 把 vbtable 放到了 CFinal 类的开头的原因,而CMid1 和 CMid2 也同样要使用这个 vbtable, 所以 这个三个的地址也就必须相同了.那 CBase 的地址是怎么出来的呢? 呃...刚刚我们说了 vbtable 放到了CFinal 的开头(vc 一定会放在开头吗?答案是不一定,这个稍后解释).在我的机器上面 final 对应内存的第一个 dword 是 0x00426030,查看这个地址,第一个dword 是 0 ,第二个就是 0x14,刚好和 pBase 的偏移相同,这个只是巧合,也许你换个类的继承体系就完全不同了,但是我只是想说明一点,基类的偏移计算是和 vbtable 的值相关联的.下面我们就来看看 vc 是怎么计算这些偏移的.<br />　　vc 在分析我们的代码的时候,生成了一份类的继承体系信息,其中有一个叫 thisDisplacement 的_PMD结构:<br /><br />　　　　<font color="#000099">struct _PMD <font color="#ff00ff">// total undocumented</font><br />　　　　{<br />　　　　　　int mdisp; <font color="#ff00ff">// i think the meaning is Multiinheritance DISPlacement</font><br />　　　　　　int pdisp; <font color="#ff00ff">// Pointer to vbtable DISPlacement</font><br />　　　　　　int vdisp; <font color="#ff00ff">// Vbtable DISPlacement</font><br />　　　　}; </font><br /><br />　　结构的名字和成员变量的名字确确实实是 vc 的名字(在 watch 窗口输入 (_PMD*)0 就能看到这个结构的详细信息),每个字段的含义却是我自己猜测出来的.mdisp 大概用来表示多重继承(包括单一继承)的时候的偏移量,pdisp 表示 vbtable 的偏移量,而 vdisp 表示类在 vbtable 里面的下标.那么有了这个结构怎样才能完成指针的转换呢?假如我们有一个派生类指针 pFinal,要转换成一个特定的基础类,我们首先要知道和这个基类对应的 _PMD 结构的信息(这个信息的获取,我暂时没有找到一个非常方便的方法,现在我使用的方法下面会有描述),有了这个信息以后,转换就方便了.首先找到 vbtabel 的地址 *(pFinal + pdisp),然后找到基类的偏移 *(*(pFinal + pdisp) + vdisp) 这个偏移值是相对vbtable的,所以还要加上 vbtable的偏移,最后加上 mdisp的偏移,如下:<br /><br />　　<font color="#000099">char *pFinal = xxx; <font color="#ff00ff">// need a init value</font><br />　　char *pBase; <font color="#ff00ff">// we must calc</font><br />　　pBase = pFinal + mdisp + *(int *)(*(int *)(pFinal + pdisp) + vdisp) + pdisp;</font><br /><br />　　<font color="#ff0000">注意: 当 pdisp &lt; 0 的时候就表示这个类没有 vbtable 直接使用 pFinal + mdisp 就得到结果了.<br />　　<font color="#00ff00">所以这个结构是一个通用的结构,专门用作类型转换,不管是有无虚继承都能使用这个结构进行类型转换.</font></font><br />　　通过这个结构,我们也能看到 vc 是怎样布局这个 object 的.<br /><br />　　看到这里,也许你要大呼一口气,妈妈呀,一个类型转换要这么的麻烦吗?我直接写 pBase = pFinal 不就可以了吗? 恭喜你还没有被我忽悠得晕头转向,哈哈.其实你写下那行语句的时候,编译器在帮你做这个转换,大约生成下面的代码<br /><br />　　　　<font color="#000099">mov eax,[pFinal] <font color="#ff00ff">;final address</font><br />　　　　mov ecx,[eax] <font color="#ff00ff">; vbtable address *(int *)(pFinal + pdisp)</font><br />　　　　mov edx,eax <font color="#ff00ff">; save to edx</font><br />　　　　add edx,[ecx + 4] <font color="#ff00ff">; ecx + 4 is (*(int *)(pFinal + pdisp) + vdisp)</font><br />　　　　mov [pBase],edx <font color="#ff00ff">; edx = pFinal + mdisp + *(int *)(*(int *)(pFinal + pdisp) + vdisp) + pdisp;</font><br />　　　　<font color="#ff00ff">; here mdisp = 0, pdisp = 0, vdisp = 4</font></font><br /><br />　　也许你要说了,我要这些东西来干什么?要转换的时候直接转换就好了,编译器会帮做,的确,大多数的时候确实是这样,但是,在某些时候却并不如此,现在你要实现一个功能,输入一个指针,输入一个 _PMD 结构,你要实现一个AdjustPointer 的函数来生成另一个指针.这个时候你也只能这样完成了,因为我没有给你两个指针的名字,就算给了你字符串形式的名字也没有用,呃....你也许会说,办法是有的,的确是有,模板就能实现这种功能,呵..这个我们暂时不讨论具体的实现细节.也许你要问了,究竟什么时候会去实现这种听都没有听过的功能,其实这个函数是真正存在的,只不过不是由你来实现的,而是 ms 的人实现的,你只用写一个 带有 c++ 异常的程序,使用 ida 反汇编,然后查找函数,就能找到这个函数了,他用来在异常处理时创建 catch 所需要的 object.至于这个详细的信息,请期待.我会最快速度写出关于 vc 是怎样实现 c++ 异常的文章来.<br /><br />　　最后了,说说那个 _PMD 结构的获取方式.看的时候不要吃惊,方法比较的麻烦,比如我想知道和 CFinal 类相关的 _PMD 信息,先新建工作,写下 throw pFinal 这样的语句,编译,在这个语句的地方设置断点,运行,转到反汇编,进入 __CxxThrowException@8 函数,这个时候不出意外你能看到一个叫 pThrowInfo 的东西(如果看不到,请打开"显示符号名"选项),在 watch 窗口里面输入pThrowInfo,展开他,看到一个pCatchableTypeArray,记录下他的 nCacthableTypes的值,然后在 watch 里面输入<br />pThrowInfo-&gt;pCatchableTypeArray-&gt;arrayOfCatchableTypes[0] 到 pThrowInfo-&gt;pCatchableTypeArray-&gt;arrayOfCatchableTypes[n], n 就是你刚刚记录的值减1,再展开他们,你就能看到一个 thisDisplacement 的数据,继续展开就是 mdisp 等等了,很是麻烦吧.哈..你已经猜到了,这个是和异常有关系的.<br /><br />　　后记: 这段时间,我一直在读些反汇编之后的代码,也颇有些心得,所以才有想法写一些文章,探讨 vc 编译器鲜为人知(太过狂妄了)的秘密,这个方面的文章也有人写过,那些文章也给我不少的启发,我不认为自己是第一个发现这些秘密的人,但是至少我自己知道的,我是第一个把这些东西写出来的人.文章里面作墨多的部分都是自己发现的.就这个文章里面的内容来说,inside the c++ object model 是有比较详细的描写,但是他并不是转换针对 vc 这个编译器的实现,而 _PMD 这个结构我也没有在什么地方见有人描述过,只是在 windows develop network 的2002年12月的杂志上看有人提到过这个结构,可惜他却没有了解(至少他在他发表文章的时候是如是说的)这个结构的用处(正是因为这个原因,我才有写这个文章以及后续文章的冲动).所以,这个文章也算是我自己的原创吧.这个文件虽然和游戏制造没有太大的关系,但是小 T 自视清高,不愿意自己的文章被一帮不懂的人评价来评价去的,所以也没有发到那些著名的 xxx 网站,只发 goldpoint.转载请注明出处(小 T 对自己的第一个原创文章比较珍惜,比较重视,谢谢).<br /><img src ="http://www.cppblog.com/stdyh/aggbug/17442.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/stdyh/" target="_blank">dyh</a> 2007-01-08 21:17 <a href="http://www.cppblog.com/stdyh/archive/2007/01/08/17442.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>文件操作eof()的问题</title><link>http://www.cppblog.com/stdyh/archive/2006/06/21/8794.html</link><dc:creator>dyh</dc:creator><author>dyh</author><pubDate>Wed, 21 Jun 2006 13:10:00 GMT</pubDate><guid>http://www.cppblog.com/stdyh/archive/2006/06/21/8794.html</guid><wfw:comment>http://www.cppblog.com/stdyh/comments/8794.html</wfw:comment><comments>http://www.cppblog.com/stdyh/archive/2006/06/21/8794.html#Feedback</comments><slash:comments>6</slash:comments><wfw:commentRss>http://www.cppblog.com/stdyh/comments/commentRss/8794.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/stdyh/services/trackbacks/8794.html</trackback:ping><description><![CDATA[大家在使用C++写操作文件的程序时,一定使用过eof()这个函数,用它来判别文件结束,但有不少也用来判别文件是否为空的.但是,这样操作的结果不是我们所想的.看下面程序:<br /><br /><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" /><span style="COLOR: #000000">#include </span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br /><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" /><br /><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #0000ff">using</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">namespace</span><span style="COLOR: #000000"> std;<br /><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" /><br /><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000"> main()<br /><img id="Codehighlighter1_52_280_Open_Image" onclick="this.style.display='none'; Codehighlighter1_52_280_Open_Text.style.display='none'; Codehighlighter1_52_280_Closed_Image.style.display='inline'; Codehighlighter1_52_280_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="Codehighlighter1_52_280_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_52_280_Closed_Text.style.display='none'; Codehighlighter1_52_280_Open_Image.style.display='inline'; Codehighlighter1_52_280_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedBlock.gif" align="top" /></span><span id="Codehighlighter1_52_280_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/images/dot.gif" /></span><span id="Codehighlighter1_52_280_Open_Text"><span style="COLOR: #000000">{<br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />    </span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000"> c </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">'</span><span style="COLOR: #000000">c</span><span style="COLOR: #000000">'</span><span style="COLOR: #000000">;<br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />    ifstream FILE(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">test.txt</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />    </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> (FILE.eof())<br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />        cout </span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">文件是空的.</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">endl;exit(</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">); <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" /><br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />    </span><span style="COLOR: #0000ff">while</span><span style="COLOR: #000000"> (</span><span style="COLOR: #000000">!</span><span style="COLOR: #000000">FILE.eof())<br /><img id="Codehighlighter1_193_239_Open_Image" onclick="this.style.display='none'; Codehighlighter1_193_239_Open_Text.style.display='none'; Codehighlighter1_193_239_Closed_Image.style.display='inline'; Codehighlighter1_193_239_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_193_239_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_193_239_Closed_Text.style.display='none'; Codehighlighter1_193_239_Open_Image.style.display='inline'; Codehighlighter1_193_239_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedSubBlock.gif" align="top" />    </span><span id="Codehighlighter1_193_239_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/images/dot.gif" /></span><span id="Codehighlighter1_193_239_Open_Text"><span style="COLOR: #000000">{<br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />        FILE.</span><span style="COLOR: #0000ff">get</span><span style="COLOR: #000000">(c);<br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />        cout </span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000"> c;<br /><img src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />    }</span></span><span style="COLOR: #000000">    <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />    system(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">pause</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />    </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br /><img src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />}</span></span><span style="COLOR: #000000"><br /><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" /><br /><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" /></span></div><p>当test.txt为空文件时,它输出的是:c<br />奇怪!应该输出是:文件是空的. while里面的操作也应该不用到的.但是结果偏偏和我们所想的相反.<br />好,那操作二进制文件又是怎样的呢?修改下为:<br />   </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"><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" /><span style="COLOR: #000000"> ifstream FILE(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">test.txt</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,ios::</span><span style="COLOR: #0000ff">in</span><span style="COLOR: #000000">|</span><span style="COLOR: #000000">ios::binary);<br /><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" />    </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> (FILE.eof())<br /><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" />        cout </span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">文件是空的.</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">    </span><span style="COLOR: #0000ff">while</span><span style="COLOR: #000000"> (</span><span style="COLOR: #000000">!</span><span style="COLOR: #000000">FILE.eof())<br /><img id="Codehighlighter1_121_171_Open_Image" onclick="this.style.display='none'; Codehighlighter1_121_171_Open_Text.style.display='none'; Codehighlighter1_121_171_Closed_Image.style.display='inline'; Codehighlighter1_121_171_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="Codehighlighter1_121_171_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_121_171_Closed_Text.style.display='none'; Codehighlighter1_121_171_Open_Image.style.display='inline'; Codehighlighter1_121_171_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedBlock.gif" align="top" />    </span><span id="Codehighlighter1_121_171_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/images/dot.gif" /></span><span id="Codehighlighter1_121_171_Open_Text"><span style="COLOR: #000000">{<br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />        FILE.read(</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">c,</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">);<br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />        cout </span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000"> c;<br /><img src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />    }</span></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">代码其他部分相同<br /><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" /></span></div><p>结果输出还是c..噢!!怎么会这样的.分明是骗人的东西嘛!!到底是什么原因呢?<br />     经过一段研究后,原来eof()返回true的条件是"读到文件结束符"，而不是文件内容的最后一个字符。<br />要清楚"文件结束符"(0xff).就是说我们文件最后的字符不是文件结束符,而最后的字符的下一位才是.所以操作再读多一次.就为什么上面if (FILE.eof())总是false的. 在一些编译器中(dev c++),它读到最后一个字符后文件位置的指针会定在那儿,所以就会重复最后一个字符.     <br />    在一个外国的CPP论坛见到一位同志的代码刚好有这解决方法.现在把上面的代码改为下面的:</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"><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" /><span style="COLOR: #000000">#include </span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">iostream.h</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br /><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" />#include </span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">stdlib.h</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br /><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" />#include </span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">fstream.h</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br /><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" /><br /><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000"> main()<br /><img id="Codehighlighter1_75_355_Open_Image" onclick="this.style.display='none'; Codehighlighter1_75_355_Open_Text.style.display='none'; Codehighlighter1_75_355_Closed_Image.style.display='inline'; Codehighlighter1_75_355_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="Codehighlighter1_75_355_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_75_355_Closed_Text.style.display='none'; Codehighlighter1_75_355_Open_Image.style.display='inline'; Codehighlighter1_75_355_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedBlock.gif" align="top" /></span><span id="Codehighlighter1_75_355_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/images/dot.gif" /></span><span id="Codehighlighter1_75_355_Open_Text"><span style="COLOR: #000000">{<br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />    </span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000"> c </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">'</span><span style="COLOR: #000000">c</span><span style="COLOR: #000000">'</span><span style="COLOR: #000000">;<br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />    ifstream FILE(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">test.txt</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />    </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> (FILE.peek() </span><span style="COLOR: #000000">==</span><span style="COLOR: #000000"> EOF)</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">修改 </span><span style="COLOR: #008000"><br /><img id="Codehighlighter1_163_220_Open_Image" onclick="this.style.display='none'; Codehighlighter1_163_220_Open_Text.style.display='none'; Codehighlighter1_163_220_Closed_Image.style.display='inline'; Codehighlighter1_163_220_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_163_220_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_163_220_Closed_Text.style.display='none'; Codehighlighter1_163_220_Open_Image.style.display='inline'; Codehighlighter1_163_220_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedSubBlock.gif" align="top" /></span><span style="COLOR: #000000">    </span><span id="Codehighlighter1_163_220_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/images/dot.gif" /></span><span id="Codehighlighter1_163_220_Open_Text"><span style="COLOR: #000000">{<br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />        cout </span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">文件是空的.</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000"> endl; <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />        exit(</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">);<br /><img src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />    }</span></span><span style="COLOR: #000000">       <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />    </span><span style="COLOR: #0000ff">while</span><span style="COLOR: #000000"> (FILE.peek() </span><span style="COLOR: #000000">!=</span><span style="COLOR: #000000"> EOF)</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">修改</span><span style="COLOR: #008000"><br /><img id="Codehighlighter1_268_314_Open_Image" onclick="this.style.display='none'; Codehighlighter1_268_314_Open_Text.style.display='none'; Codehighlighter1_268_314_Closed_Image.style.display='inline'; Codehighlighter1_268_314_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_268_314_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_268_314_Closed_Text.style.display='none'; Codehighlighter1_268_314_Open_Image.style.display='inline'; Codehighlighter1_268_314_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedSubBlock.gif" align="top" /></span><span style="COLOR: #000000">    </span><span id="Codehighlighter1_268_314_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/images/dot.gif" /></span><span id="Codehighlighter1_268_314_Open_Text"><span style="COLOR: #000000">{<br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />        FILE.</span><span style="COLOR: #0000ff">get</span><span style="COLOR: #000000">(c);<br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />        cout </span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000"> c;<br /><img src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />    }</span></span><span style="COLOR: #000000">    <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />    system(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">pause</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />    </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br /><img src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />}</span></span><span style="COLOR: #000000"><br /><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" /></span></div><p>主要的是把eof()改为peek() == EOF来判别,其中peek()是取文件当前指针,EOF是文件尾标符,它的值为-1.所以采用这种方法就解决上面eof()的问题了..这种方法也可以用在读写二进制文件中.</p><img src ="http://www.cppblog.com/stdyh/aggbug/8794.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/stdyh/" target="_blank">dyh</a> 2006-06-21 21:10 <a href="http://www.cppblog.com/stdyh/archive/2006/06/21/8794.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>