﻿<?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++博客-乱八七糟的代码-随笔分类-工作记录~~everyday</title><link>http://www.cppblog.com/zqsand/category/12249.html</link><description>啥是子标题</description><language>zh-cn</language><lastBuildDate>Fri, 22 Jan 2010 12:27:00 GMT</lastBuildDate><pubDate>Fri, 22 Jan 2010 12:27:00 GMT</pubDate><ttl>60</ttl><item><title>More Effective C++ (1)</title><link>http://www.cppblog.com/zqsand/archive/2010/01/18/105931.html</link><dc:creator>rikisand</dc:creator><author>rikisand</author><pubDate>Mon, 18 Jan 2010 06:16:00 GMT</pubDate><guid>http://www.cppblog.com/zqsand/archive/2010/01/18/105931.html</guid><wfw:comment>http://www.cppblog.com/zqsand/comments/105931.html</wfw:comment><comments>http://www.cppblog.com/zqsand/archive/2010/01/18/105931.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/zqsand/comments/commentRss/105931.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/zqsand/services/trackbacks/105931.html</trackback:ping><description><![CDATA[
<p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">第四章&nbsp; 效率</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">&#183;&#183;&#183;&#183;&#183;&#183;条款16 记住80-20准则</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">大约20%的代码使用了80%的资源，程序的整体性能是由该程序的一小部分代码所决定的~</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">可行的办法是使用程序分析器（profiler）来找到导致性能瓶颈的拿20%的程序~</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">而且要针对造成瓶颈的资源来使用相应的分析器~</font></p> <p><font face="YaHei Consolas Hybrid" size="3"></font><font color="#ffff80">&nbsp;</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">&#183;&#183;&#183;&#183;&#183;&#183;条款17&nbsp; 考虑使用延迟计算</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">延迟计算： 也就是说知道程序要求给出结果的时候才进行运算~ 很好理解，和操作系统中的cow copy on write 一个原理~</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">四个使用场景：</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">~1~ 引用计数 ：</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">　　class String{&#8230;};</font></p> <blockquote> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">String s1 = &#8220;hello&#8221;;</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">String s2 = s1 ;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //call string Copy ctor</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">通常情况下，s2赋值后会有一个hello的拷贝，者通常需要使用new操作符分配内存，之后strcpys1</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">的数据给他，但如果下面的操作如下的话：</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">cout &lt;&lt; s1 ;</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">cout &lt;&lt; s1 + s2;</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">这种情况下如果只增加s1的引用计数，而s2只是共享s1的值就可以了。只有在需要对s2进行修改或者s1进行修改时，才需要真正拷贝给s2一个副本，引用计数的实现在29条款</font></p></blockquote> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">~2~区分读写操作</font></p> <blockquote> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">如： String s = &#8220;homer&#8217;s all&#8221;;</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">cout&lt;&lt; s[3];</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">s[3] = &#8216;x&#8217;;</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">在进行读操作时，使用引用计数是开销很小的，然而写操作必须生成新的拷贝。通过条款30的代理类我们可以把判断读写操作推迟到我们能够决定哪个是正确操作的时候</font></p></blockquote> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">~3~延迟读取</font></p> <blockquote> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">假设程序使用了包含许多数据成员的大对象，这些对象必须在每次程序运行的时候保留下来，因此存进了数据库。某些时候从database中取出所有数据是没有必要的，比如他只访问该对象中的一个数据成员。此时，应该对对象进行处理，只有对象内部某一个特定的数据成员被访问的时候才把他取出来。类似于os中的按需换页~</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">class LargeObject{</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">&nbsp;&nbsp;&nbsp; LargeObject(ObjectID id);</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">const string&amp; field1() const;</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">int field2() const;</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">double field3() const;</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">const string&amp; field4() const;</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">private:</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">ObjectID id;</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">mutable string* field1value;</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">mutable int&nbsp;&nbsp; * fieldValue;</font></p> <p><font color="#ffff80"><font face="YaHei Consolas Hybrid" size="3">}</font><font face="YaHei Consolas Hybrid" size="3">;</font></font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">LargeObject::LargeObject(ObjectID id):oid(id),fieldValue(0),&#8230;{}</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">const string&amp; LargeObject::field1()const{</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">&nbsp;&nbsp; if(fieldValue == 0){</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //read the data for field 1 from database and make field1 point to it</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">&nbsp;&nbsp; }</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">&nbsp;&nbsp; return&nbsp; *field1Value; </font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">}</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">实施lazy fetching 任何成员函数都需要初始化空指针以指向有效数据。但是const成员函数中，试图修改数据编译器会报错。所以声明字段指针为 mutable ，表示任何函数都可以修改,即便在const成员函数中也可以~ 条款28中的智能指针可以让这一方法更灵活</font></p></blockquote> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">~3~延迟表达式求值</font></p> <blockquote> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">数值计算领域，也在使用延迟计算。例如</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">matrix&lt;int&gt; m1(1000,1000);</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">matrix&lt;int&gt; m2(1000,1000);</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">matrix&lt;int&gt; m3 = m1 + m2;</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">如果此时计算出m3的话运算量非常之大~</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">但是如果此时程序为：</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">m3 = m4*m1;</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">那么刚才的计算就没必要了</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">如果cout&lt;&lt; m3[4];</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">我们只需要计算m3[4]就可以了，其他的值等到确实需要他们的时候才予以计算~如果运气够好的话永远不需要计算~ </font></p></blockquote> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">总结，延迟计算只有当软件在某种程度下可以被避免时候才有意义~只有延迟计算得到的好处大于设计它与实现它花费的精力时才有意义~</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">&#183;&#183;&#183;&#183;&#183;&#183;&#183;条款18： 分期摊还预期的计算开销</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">提前计算~ over-eager evaluation 在系统要求你做某些事情之前就做了他~</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">例如：大量数据的集合</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">template&lt;class NumericalType&gt;</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">class DataCollection}{</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">public:</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">&nbsp; NumericalType min() const;</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">&nbsp; NumericalType max() const;</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">&nbsp; NumericalType avg() const;</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">};</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">使用提前计算，我们随时跟踪目前集合的最大最小平均值，这样 min max avg被调用时候，我们可以不用计算立刻返回正确的数值~~ </font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">提前计算的思想便是：如果预计某个计算会被频繁调用，你可以通过设计你的数据结构以更高效的办法处理请求，这样可以降低每次请求的平均开销~</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">最简单的做法为 缓存已经计算过并且很可能不需要重新计算的那些值~</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">例如在数据库中存有很多办公室的电话号码，程序在每次查询电话时先查询本地的缓存如果没找到再去访问数据库，并且更新缓存，这样使用缓存平均访问时间要大大减小。</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">预处理也是一种策略。</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">例如设计动态数组的时候，当索引下标大于已有最大范围时候，需要new出新的空间，如果申请两倍于索引的大小的话就可以避免频繁的申请操作~~~</font></p> <p><font face="YaHei Consolas Hybrid" size="3"></font><font color="#ffff80">&nbsp;</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;条款 19 ： 了解临时对象的来源</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">如果一个对象被创建，不是在堆上，没有名字，那么这个对象就是临时对象。</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">通常产生于： 为了使函数调用能够成功而进行的隐式转换，或者函数返回对象是进行的隐式转换。由于构造和析构他们带来的开销可以给你的程序带来显著的影响，因此有必要了解他们~</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">~1首先考虑为了函数调用能通过产生的临时对象的情况</font></p> <blockquote> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">传给某个函数的对象的类型和这个函数所绑定的参数类型不一致的情况下会出现这种情况。</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">例如：</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">size_t count(const string&amp; str,char ch);</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">函数定义为计算str中ch的数量</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">char buffer[100];</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">cout&lt;&lt;count(buffer,&#8216;c&#8217;);</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">传入的是一个char数组，此时编译器会调用str的构造函数，利用buffer来创建一个临时对象。</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">在调用完countChar语句后这个临时对象就被自动销毁了~</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">仅当传值或者const引用的时候才会发生这样的类型转换~当传递一个非常量引用的时候，不会发生。</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">void uppercasify(string&amp; str); //change all chars in str to upper case;</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">在这个例子中使用char数组就不会成功~</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">因为程序作者声明非常量引用也就是想让对引用的修改反映在他引用的对象身上，但是如果此时生成了临时对象，那么这些修改只是作用在临时对象身上，也就不是作者的本意了。所以c++禁止非常量引用产生临时对象。</font></p></blockquote> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">~2 函数返回对象时候会产生临时对象</font></p> <blockquote> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">例如： const Number operator + ( const Number&amp; lhs,const Number&amp; rhs);</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">这个函数返回一个临时对象，因为他没有名字，只是函数的返回值。</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">条款20中 ，会介绍让编译器对已经超出生存周期的临时对象进行优化</font></p></blockquote> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3"></font>&nbsp;</p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;条款20： 协助编译器实现返回值优化</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">返回值优化：返回带有参数的构造函数。</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">cosnt Rational operator * (cosnt Rational&amp; lhs,const Rational&amp; rhs){</font></p> <p><font color="#ffff80"><font face="YaHei Consolas Hybrid" size="3">&nbsp;&nbsp;&nbsp; return Rational(lhs.numerator()*rhs.numerator(),lhs.denomiator()*rhs.denominator()</font><font face="YaHei Consolas Hybrid" size="3">};</font></font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">c++允许编译器针对超出生命周期的临时对象进行优化。因此如果调用Rational c=a*b；</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">c++允许编译器消除operator*内部的临时变量以及operator*返回的临时变量，编译器可以把return表达式所定义的返回对象构造在分配给c的内存上。如果这样做的话那么调用operator*所产生的临时对象所带来的开销就是0~ 我们可以把operator 声明为内联函数而去除调用构造函数带来的开销~</font></p> <p><font color="#ffff80">#include &lt;iostream&gt;<br>#include &lt;string&gt;<br>#include "time.h"<br>using namespace std;<br>char buffer[100]; <br>class number{<br>public:<br>&nbsp;&nbsp;&nbsp; const friend&nbsp; number operator * (const number&amp; rhs,const number lhs);<br>&nbsp;&nbsp;&nbsp; number(){}<br>&nbsp;&nbsp;&nbsp; number(int b):a(b){}<br>&nbsp;&nbsp;&nbsp; number(const number&amp; rhs){<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; a = rhs.a;<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int a; <br>};<br>const number operator*(const number&amp; rhs,const number lhs){<br>&nbsp;&nbsp;&nbsp; number res;<br>&nbsp;&nbsp;&nbsp; res.a = rhs.a * lhs.a;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return res;<br>&nbsp;&nbsp;&nbsp; /*return number(rhs.a*lhs.a);*/<br>}<br>//CLOCKS_PER_SEC<br>int main()<br>{<br>&nbsp;&nbsp;&nbsp; clock_t start = clock();<br>&nbsp;&nbsp;&nbsp; number A(5);number B(6);<br>&nbsp;&nbsp;&nbsp; for(int i=0;i&lt;100000000;i++)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; number C = A*B; </font> </p><p><font color="#ffff80">&nbsp;&nbsp;&nbsp; clock_t end = clock();<br>&nbsp;&nbsp;&nbsp; cout&lt;&lt;double(end-start)/CLOCKS_PER_SEC&lt;&lt;endl;<br>}</font> </p><p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">通过上面的程序运行 如果没有返回值优化 运行时间 15.9s 优化后是 10.1s </font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">还是很显著的么 快了33% ，如果这种情况出现在程序的热点处~效果就很好了</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3"></font>&nbsp;</p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;条款21 ： 通过函数重载避免隐式类型转换</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">例子：</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">class upint{</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3"> public:</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3"> upint();</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3"> upint(int value);</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">};</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">cosnt upint operator+(const upint&amp;lhs,const upint&amp;rhs);</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">upint up1,up2;</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">upint up3 = up1+up2;</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">upi3 = up1 +10;</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">upi4 = 10+ upi2;</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">这些语句也可以通过，因为创建了临时对象，通过带有int的构造函数产生了临时的upint对象，如果我们不愿意为这些临时对象的产生与析构付出代价，我们需要做什么：</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">我们声明 cosnt upint operator+(cosnt upint&amp;lhs,int rhs);</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">cosnt upint operator+(int lhs,const upint&amp; rhs);</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">就可以去除临时对象产生了~</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">但是如果我们写了 const upint operator+(int lhs,int rhs); // 错了~</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">c++规定，每一个被重载的运算符必须至少有一个参数属于用户自定义类型，int并不是自定义类型所以上面的不对的</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">同样的如果希望string char* 作为参数的函数，都有理由进行重载而避免隐形类型转换（仅仅在有必要的时候，也就是说他们可以对程序效率起到很大帮助的时候~）</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;条款： 考虑使用 op = 来取代 单独的 op运算符</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">class Rational{</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">public:</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">&nbsp;&nbsp; Rational&amp; operator+=(const Rational&amp; rhs);</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">&nbsp;&nbsp; Rational&amp; operator-=(const Rational&amp; rhs);</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">}</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">const Rational operator+(cosnt Rational&amp; lhs,const Rational &amp; rhs){</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">&nbsp;&nbsp;&nbsp; return Rational(lhs)+=rhs;</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">}</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">利用+= -=来实现+ -可以保证运算符的赋值形式与单独使用运算符之间存在正常的关系。</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">Rational a,b,c,d,result;</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">result = a+ b+c+d; // 可能要用到3个临时对象</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">result +=a;result+=b;result+=c; //没有临时对象</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">前者书写维护都更容易，而且一般来说效率不存在问题，但是特殊情况下后者效率更高更可取</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">注意：</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3"> 如果+的实现是这样的：</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3"> const T operator+ (constT&amp; lhs,const T&amp;rhs){</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">&nbsp;&nbsp;&nbsp;&nbsp; T result(lhs);</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">&nbsp;&nbsp;&nbsp;&nbsp; return result += rhs;</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3"> }</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">这个模版中包含有名字对象result，这个对象有名字意味着返回值优化不可用~~~~~~~~&#183;</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3"></font>&nbsp;</p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">&#183;&#183;&#183;&#183;&#183;&#183;&#183;条款23 ： 考虑使用其他等价的程序库</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">主旨：</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">提供类似功能的程序库通常在性能问题上采取不同的权衡措施，比如iostream和stdio，所以通过分析程序找到软件瓶颈之后，可以考虑是否通过替换程序库来消除瓶颈~~~~</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3"></font>&nbsp;</p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3"></font>&nbsp;</p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">&#183;&#183;&#183;&#183;&#183;&#183;条款24 : 理解虚函数，多重继承，虚基类以及 RTTI 带来的开销</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">虚函数表：vtabs 指向虚函数表的指针 vptrs</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">程序中每个声明了或者继承了的虚函数的类都具有自己的虚函数表。表中的各个项就是指向虚函数具体实现的指针。</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">class c1{</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">&nbsp;&nbsp; c1();</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">&nbsp;&nbsp; virtual ~c1();</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">&nbsp;&nbsp; virtual void f1();</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">&nbsp;&nbsp; virtual int f2(char c)const;</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">&nbsp;&nbsp; virtual void f3(const string&amp; s);</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">};</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">c1 的虚函数表包括： c1::~c1 c1::f1 c1::f2 c1::f3</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">class c2:public c1{</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">&nbsp;&nbsp; c2();</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">&nbsp;&nbsp; virtual ~c2();</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">&nbsp;&nbsp; virtual void f1();</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">&nbsp;&nbsp; virtual void f5(char *str);</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">};</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">它的虚函数表入口指向的是那些由c1声明但是c2没有重定义的虚函数指针：</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">c2::~c2&nbsp; c2::f1 c1::f2 c1::f3 c2::f5</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">所以开销上： 必须为包含虚函数的类腾出额外的空间来存放虚函数表。一个类的虚函数表的大小取决于它的虚函数的个数，虽然每一个类只要有一个虚函数表，但是如果有很多类或者每个类具有很多个虚函数，虚函数表也会占据很大的空间，这也是mfc没有采用虚函数实现消息机制的一个原因。</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">由于每一个类只需要一个vtbl的拷贝，把它放在哪里是一个问题：</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">一种：为每一个需要vtbl的目标文件生成拷贝，然后连接时取出重复拷贝</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">或者：更常见的是采用试探性算法决定哪一个目标文件应该包含类的vtbl。试探：一个类的vtbl通常产生在包含该类第一个非内联，非纯虚函数定义的目标文件里。所以上面c1类的vtbl将放在c1::~c1 定义的目标文件里。如果所有虚函数都声明为内联，试探性算法就会失败，在每一个目标文件就会有vtbl。所以一般忽略虚函数的inline指令。</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">如果一个类具有虚函数，那么这个类的每一个对象都会具有指向这个虚函数表的指针，这是一个隐藏数据成员vptr~被编译器加在某一个位置。</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">此处第二个开销：你必须在每一个对象中存放一个额外的指针~</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">如果对象很小这个开销就十分显著~~因为比例大~</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">此时 void makeCall(c1* pc1){</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">&nbsp;&nbsp; pc1-&gt;f1();</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">}</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">翻译为 (*pc1-&gt;vptr[i])(pc1);</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">根据vptr找到vtbl 这很简单，</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">在vtbl找到调用函数对应的函数指针，这个步骤也很简单，因为编译器为虚函数表里的每一个函数设置了唯一的索引</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">然后调用指针所指向的函数~</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">这样看来，调用虚函数与普通函数调用的效率相差无几，只多出几个指令。</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">虚函数真正的开销与内联函数有关~：在实际应用中，虚函数不应该被内联，因为内联意味着在编译时刻用被调用函数的函数体来代替被调用函数。但是虚函数意味着运行时刻决定调用哪个一函数，so~~~虚函数付出的第三个代价啊：~不能内联（通过对象调用虚函数的时候，这些虚函数可以内联，但是大多数虚函数通过指针或者以用来调用的）。</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">~多重继承的情况</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">多重继承一般要求虚基类。没有虚基类，如果一个派生类具有多个通向基类的继承路径，基类的数据成员会被复制到每一个继承类对象里，继承类与基类间的每一条路径都有一个拷贝。</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">有了虚基类，通常使用指向虚基类的指针作为避免重复的手段，这样需要在对象内部嵌入一个或者多个指针~也带来了一定的开销~</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">例如菱形继承 ： </font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">class A{};</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">class B:virtual public A{};</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">class C:virtual public A{};</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">class D:public B,public C{};</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">这里A是一个虚基类，因为B和C虚拟继承了他。</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">对象 D 的布局：</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">B data</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">vptr</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">pointer to virtual base class</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">C data</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">vptr</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">pointer to virtual base class</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">D data members</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">A data members</font></p> <p><font face="YaHei Consolas Hybrid" color="#ffff80" size="3">vptr</font></p> <p><font face="YaHei Consolas Hybrid" color="#8000ff" size="3"><font color="#ffff80">上面四个类，只有三个vptr，因为B和D可以共享一个vptr</font>&nbsp; <font color="#ff0000">（为啥？）</font></font></p> <p><font face="YaHei Consolas Hybrid" color="#0080ff" size="3">现在我们已经看到虚函数如何使对象变得更大，以及为何不能把它内联了~</font></p> <p><font face="YaHei Consolas Hybrid" color="#0080ff" size="3">下面我们看看RTTI的开销 runtime type identifycation 所需要的开销</font></p> <p><font face="YaHei Consolas Hybrid" color="#0080ff" size="3">通过rtti我们可以知道对象和类的有关信息，所以肯定在某个地方存储了这些供我们查询的信息，这些信息被存储在type_info 类型的对象里，你可以通过typeid运算符访问一个类的type_info对象。</font></p> <p><font face="YaHei Consolas Hybrid" color="#0080ff" size="3">每个类仅仅需要一个RTTI的拷贝，规范上只保证提供哪些至少有一个虚函数的对象的准确的动态类型信息~</font></p> <p><font face="YaHei Consolas Hybrid" color="#0080ff" size="3">why？和虚函数有啥关系~ 因为rtti设计在vtbl里</font></p> <p><font face="YaHei Consolas Hybrid" color="#0080ff" size="3">vtbl的下标0包含指向type_info对象的指针。所以使用这种实现方法，消费的空间是vtbl中占用一个额外的单元再加上存储type_info对象所需要的空间。</font></p> <p><font face="YaHei Consolas Hybrid" color="#0080ff" size="3"></font>&nbsp;</p> <p><font face="YaHei Consolas Hybrid" color="#0080ff" size="3">------------------------罪恶的结束线 OVER~------------------------------------------</font></p><img src ="http://www.cppblog.com/zqsand/aggbug/105931.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/zqsand/" target="_blank">rikisand</a> 2010-01-18 14:16 <a href="http://www.cppblog.com/zqsand/archive/2010/01/18/105931.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>断言的使用</title><link>http://www.cppblog.com/zqsand/archive/2010/01/17/105886.html</link><dc:creator>rikisand</dc:creator><author>rikisand</author><pubDate>Sun, 17 Jan 2010 11:36:00 GMT</pubDate><guid>http://www.cppblog.com/zqsand/archive/2010/01/17/105886.html</guid><wfw:comment>http://www.cppblog.com/zqsand/comments/105886.html</wfw:comment><comments>http://www.cppblog.com/zqsand/archive/2010/01/17/105886.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/zqsand/comments/commentRss/105886.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/zqsand/services/trackbacks/105886.html</trackback:ping><description><![CDATA[
<p>解决项目的问题，意识到断言的重要性。如果一个程序在某处遇到了非法的值，那么最好的情况便是在此刻停下报错，最坏的情况便是程序不吭不响的执行着~~直到你发现他执行的方式极为诡异，此时，你要花九牛二虎之力才能找到错误所在之处~~~~</p> <p>学习一下断言吧：</p> <p><font size="3"><font face="YaHei Consolas Hybrid" color="#008000">&#183;&#183;&#183;&#183;&#183;&#183;&#183;什么是断言</font></font></p> <p><font face="YaHei Consolas Hybrid" color="#008000" size="3">在某处判断某一个表达式的值为真或者假，如果假则输出错误消息并停止程序的执行~</font></p> <p><font face="YaHei Consolas Hybrid" color="#008000" size="3">assert是宏，而不是函数，只在debug版本中有效，因此无需在release版本删除。</font></p> <p><font face="YaHei Consolas Hybrid" color="#008000" size="3">&#183;&#183;&#183;&#183;&#183;&#183;&#183;哪几种断言</font></p> <p><font face="YaHei Consolas Hybrid" color="#008000" size="3">MFC </font></p> <p><font face="YaHei Consolas Hybrid" color="#008000" size="3">ASSERT</font></p> <p>void foo(char* p,int size)<br>{<br>ASSERT(p != 0); // 验证缓冲区指针<br>ASSERT((size &gt;= 100); // 确认缓冲区大小至少为100字节<br>// foo 函数的其它计算过程<br>}<br>如果没有定义_DEBUG预处理符，则该语句不会真正生成代码。Visual C++会在调试模式编译时自动定义_DEBUG，而在发行模式下，该预处理符是不存在的。如果定义了_DEBUG，则上述两个断言生成的代码类如： <br>//ASSERT(p != 0);<br>do<br>{<br>if(!(p != 0) &amp;&amp; AfxAssertFailedLine(__FILE__, __LINE__))<br>AfxDebugBreak();<br>} while(0);<br>//ASSERT((size &gt;= 100);<br>do<br>{<br>if(!(size &gt;= 100) &amp;&amp; AfxAssertFailedLine(__FILE__,__LINE__))<br>AfxDebugBreak();<br>}while(0);  </p><p><font face="YaHei Consolas Hybrid" color="#008080" size="3">ASSERT_KINDOF(classname,pObject); ASSERT_KINDOF(CDocument,pDocument);</font></p> <p><font face="YaHei Consolas Hybrid" color="#008080" size="3">检验pObject指向的对象是classname类的一个对象或者其派生类的对象</font></p> <p><font face="YaHei Consolas Hybrid" color="#008080" size="3">ASSERT_VALID(pObject); pObject 必须是一个派生于CObject类的类对象，会调用其重写的AssertValid函数 ，例如</font></p> <p>如果使用应用向导或类向导生成基于MFC的类，通常会得到AssertValid()的骨架，最好改写这些骨架代码以增加最基本的完整性检查。下面是一个典型的例子，类Sample从CObject继承，假定它含有职员名字及其薪水： <br>class Sample : public CObject<br>{<br>&nbsp;&nbsp;&nbsp; protected:<br>&nbsp;&nbsp;&nbsp; CString m_Name; // 职员名字<br>&nbsp;&nbsp;&nbsp; double m_Salary; // 薪水<br>public:<br>&nbsp;&nbsp;&nbsp; Sample(LPCTSTR name,double salary) : m_Name(name), m_Salary(salary) {}<br><em>&nbsp;&nbsp; #ifdef _DEBUG<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; virtual void AssertValid() const;<br>&nbsp;&nbsp;&nbsp; #endif</em><br>};<br><em>#ifdef _DEBUG<br>void Sample::AssertValid() const<br>{<br>&nbsp;&nbsp;&nbsp; CObject::AssertValid(); // 验证基类<br>&nbsp;&nbsp;&nbsp; ASSERT(!m_Name.IsEmpty()); // 验证职员名字<br>&nbsp;&nbsp;&nbsp; ASSERT(m_Salary &gt; 0); // 验证薪水<br>}<br>#endif</em>  </p><p><font face="YaHei Consolas Hybrid" color="#408080" size="3">CRT assertion</font></p> <p><font face="YaHei Consolas Hybrid" color="#408080" size="3">_ASSERT 和&nbsp; _ASSERTE 后一个会在出错时同时打印出条件判断句</font></p> <p><font face="YaHei Consolas Hybrid" color="#408080" size="3">ANSI</font></p> <p><font face="YaHei Consolas Hybrid" color="#408080" size="3">assert()</font></p> <p><font face="YaHei Consolas Hybrid" color="#408080" size="3">注意：assert用于检测非法的输入，但是合法的输入并不一定是正确的，例如：</font></p> <p><font face="YaHei Consolas Hybrid" color="#408080" size="3">int pB = (int*)malloc(sizeof(int)*1000);</font></p> <p><font face="YaHei Consolas Hybrid" color="#408080" size="3">assert(pB!=NULL) //错误的使用assert 他会在release版本失效~也就是说assert不应该对程序产生副作用</font></p> <p><font face="YaHei Consolas Hybrid" color="#408080" size="3">正确的做法：</font></p> <p><font face="YaHei Consolas Hybrid" color="#408080" size="3">int pB = (int*) malloc(sizeof(int)*1000);</font></p> <p><font face="YaHei Consolas Hybrid" color="#408080" size="3">if(pB == NULL)</font></p> <p><font face="YaHei Consolas Hybrid" color="#408080" size="3">{<br>&nbsp;&nbsp; //错误处理</font></p> <p><font face="YaHei Consolas Hybrid" color="#408080" size="3">}</font></p> <p><font face="YaHei Consolas Hybrid" color="#408080" size="3">else{</font></p> <p><font face="YaHei Consolas Hybrid" color="#408080" size="3">}</font></p> <p><font face="YaHei Consolas Hybrid" color="#408080" size="3">另一个例子：</font></p> <p><font face="YaHei Consolas Hybrid" color="#408080" size="3">void draw(){</font></p> <p><font face="YaHei Consolas Hybrid" color="#408080" size="3">&nbsp;&nbsp; CFigure* pF = getCF();</font></p> <p><font face="YaHei Consolas Hybrid" color="#408080" size="3">&nbsp;&nbsp; assert(pf!=NULL);</font></p> <p><font face="YaHei Consolas Hybrid" color="#408080" size="3">&nbsp;&nbsp; if(pf == NULL){}</font></p> <p><font face="YaHei Consolas Hybrid" color="#408080" size="3">&nbsp;&nbsp; else{</font></p> <p><font face="YaHei Consolas Hybrid" color="#408080" size="3">&nbsp;&nbsp; }</font></p> <p><font face="YaHei Consolas Hybrid" color="#408080" size="3">}</font></p> <p><font face="YaHei Consolas Hybrid" color="#408080" size="3">此处，对于getCF来说返回值为NULL是非法的，如果他的返回值可能为null就没必要加上assert语句。</font></p> <p><font face="YaHei Consolas Hybrid" color="#408080" size="3">而下面的if语句则是为了防止release版本出现null指针的情况。 </font></p> <p><font face="YaHei Consolas Hybrid" size="3"></font><font color="#408080">&nbsp;</font></p> <p><font face="YaHei Consolas Hybrid" size="3"></font><font color="#408080">&nbsp;</font></p> <p><font face="YaHei Consolas Hybrid" color="#408080" size="3">VERIFY()</font></p> <p><font color="#408080">由于ASSERT仅在程序的调试版起作用，测试表达式总是被动的。也就是说，它们不能包含赋值、增量、减量等真正改变数据的操作。但有时候我们需要验证一个主动表达式，比如赋值语句。这时可以使用VERIFY代替ASSERT。下面是一个例子： <br>void foo(char* p,int size)<br>{<br>char* q; // 指针的副本<br><em>VERIFY(q = p);</em> // 拷贝指针并执行验证<br>ASSERT((size &gt;= 100); // 确保缓冲区大小至少为100字节<br>// 执行 foo 的其它操作<br>}<br>在调试模式下ASSERT和VERIFY是相同的。但在release模式下，VERIFY能够继续对表达式求值（但不再进行断言检验），而ASSERT语句在效果上就如同已经删除了一样。 <br>尽管在MFC源代码中可以找到一些应用VERIFY的例子，但ASSERT用得更为普遍。一些程序员总是完全避免使用VERIFY，因为他们已经习惯于使用被动断言。请记住，如果在ASSERT语句中使用了主动表达式，编译器不会发出任何警告。在发行模式下编译时该表达式会被直接删除，从而导致程序运行的错误。由于发行版程序不含调试信息，这种类型的错误是很难找到原因的。 </font> </p><p><font face="YaHei Consolas Hybrid" size="3"></font><font color="#408080">&nbsp;</font></p> <p><font face="YaHei Consolas Hybrid" color="#004080" size="3"></font>&nbsp;</p> <p><font face="YaHei Consolas Hybrid" color="#004080" size="3"></font>&nbsp;</p> <p><font face="YaHei Consolas Hybrid" color="#004080" size="3"></font>&nbsp;</p> <p><font face="YaHei Consolas Hybrid" color="#004080" size="3"></font>&nbsp;</p> <p><font face="YaHei Consolas Hybrid" color="#004080" size="3"></font>&nbsp;</p> <p><font face="YaHei Consolas Hybrid" color="#004080" size="3"></font>&nbsp;</p> <p><font face="YaHei Consolas Hybrid" color="#004080" size="3"></font>&nbsp;</p> <p><font face="YaHei Consolas Hybrid" color="#004080" size="3"></font>&nbsp;</p> <p><font face="YaHei Consolas Hybrid" color="#004080" size="3"></font>&nbsp;</p> <p><font face="YaHei Consolas Hybrid" color="#004080" size="3"></font>&nbsp;</p> <p><font face="YaHei Consolas Hybrid" color="#004080" size="3"></font>&nbsp;</p> <p><font face="YaHei Consolas Hybrid" color="#004080" size="3"></font></p><img src ="http://www.cppblog.com/zqsand/aggbug/105886.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/zqsand/" target="_blank">rikisand</a> 2010-01-17 19:36 <a href="http://www.cppblog.com/zqsand/archive/2010/01/17/105886.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>c++ RTTI (1)</title><link>http://www.cppblog.com/zqsand/archive/2010/01/03/104714.html</link><dc:creator>rikisand</dc:creator><author>rikisand</author><pubDate>Sun, 03 Jan 2010 09:59:00 GMT</pubDate><guid>http://www.cppblog.com/zqsand/archive/2010/01/03/104714.html</guid><wfw:comment>http://www.cppblog.com/zqsand/comments/104714.html</wfw:comment><comments>http://www.cppblog.com/zqsand/archive/2010/01/03/104714.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/zqsand/comments/commentRss/104714.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/zqsand/services/trackbacks/104714.html</trackback:ping><description><![CDATA[
<p><font face="YaHei Consolas Hybrid">项目中遇到了 RTTI 先学一部分 c++ primer内容</font></p> <ol> <li> <div align="left"><font face="YaHei Consolas Hybrid" color="#ff0080" size="5"><u><strong>运行时类型识别：</strong></u></font></div></li></ol> <p align="left"><font face="YaHei Consolas Hybrid">程序可以使用<font color="#008000">基类的指针</font>或者引用来检索这些指针或引用所指对象的实际派生类型</font></p> <p align="left"><font face="YaHei Consolas Hybrid">标准库提供了两个操作符： </font></p> <blockquote> <p align="left"><font face="YaHei Consolas Hybrid">1. typeid&nbsp;&nbsp;&nbsp; 他可以返回指针或者引用所指向对象的实际类型</font></p> <p align="left"><font face="YaHei Consolas Hybrid">2. dynamic_cast&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; </font></p></blockquote> <p align="left"><font face="YaHei Consolas Hybrid">对于不带虚函数的类在编译时期执行，否则在运行期间执行</font></p> <p align="left"><font face="YaHei Consolas Hybrid">使用时机：</font></p> <blockquote> <p align="left"><font face="YaHei Consolas Hybrid">基类指针调用派生类成员函数的话，一般应使用虚函数，这样编译器会根据对象的实际类型来选择正确的函数。但是某些情况下无法使用虚函数，那么此</font></p> <p align="left"><font face="YaHei Consolas Hybrid">时如果需要使用基类指针调用派生类成员函数便需要使用RTTI强制转换，而且<font color="#000080">必须检查转换是否成功</font>了</font></p></blockquote> <p align="left"><font face="YaHei Consolas Hybrid" color="#ff0000" size="4"><strong><u>(一) Dynamic_cast</u></strong></font></p> <p align="left"><font face="YaHei Consolas Hybrid">dynamic_cast 如果转换到指针失败则返回 0 如果转换到引用类型失败则抛出 bad_cast 异常</font></p> <p align="left"><font face="YaHei Consolas Hybrid">对指针操作：</font></p> <p align="left"><font face="YaHei Consolas Hybrid">if(Derived *derivedPtr = dynamic_cast&lt;Derived*&gt; (basePtr)){</font></p> <p align="left"><font face="YaHei Consolas Hybrid">&nbsp;&nbsp;&nbsp; //basePtr point to a derived object;</font></p> <p align="left"><font face="YaHei Consolas Hybrid">}else{</font></p> <p align="left"><font face="YaHei Consolas Hybrid">&nbsp;&nbsp; //basePtr point to a base object;</font></p> <p align="left"><font face="YaHei Consolas Hybrid">}</font></p> <p><font face="YaHei Consolas Hybrid">在 if 语句中进行检查 1.条件代码内部知道 derivedPtr 的类型 2.不可能在测试代码和使用代码中加入代码，也就是说不会在没有测试前就使用derivedPtr 3.如果失败外部不会使用未绑定的指针derivedPtr</font></p> <p><font face="YaHei Consolas Hybrid">对引用操作：</font></p> <p><font face="YaHei Consolas Hybrid">因为不存在空引用所以转换失败抛出异常</font></p> <p><font face="YaHei Consolas Hybrid">void f(const Base&amp; b){</font></p> <p><font face="YaHei Consolas Hybrid">&nbsp;&nbsp;&nbsp; try{</font></p> <p><font face="YaHei Consolas Hybrid">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; const Derived &amp;d = dynamic_cast&lt;const Derived&amp;&gt; (b);</font></p> <p><font face="YaHei Consolas Hybrid">&nbsp;&nbsp;&nbsp; }catch(bad_cast){</font></p> <p><font face="YaHei Consolas Hybrid">&nbsp;&nbsp;&nbsp; }</font></p> <p><font face="YaHei Consolas Hybrid">}</font></p> <p><u><strong><font color="#ff0000" size="5">(二) typeid</font></strong></u> </p> <p>typeid(e) e是任意的表达式或者类型名</p> <p>Base *bp; </p> <p>Derived *dp;</p> <p>//compare type at run time of two objects</p> <p>if(typeid(*bp)==typeid(*dp)){</p> <p>&nbsp;&nbsp;&nbsp; //bp dp point to objects of the same type</p> <p>}</p> <p>if(typeid(*bp)==typeid(Derived)){</p> <p>&nbsp;&nbsp;&nbsp; //bp actually point to a Derived</p> <p>}</p> <p><strong><font color="#80ff00">注意typeid 测试的是 *bp 对象</font></strong></p> <p>//test always fails: The type of bp if pointer to Base</p> <p>if(typeid(bp)==typeid(Derived)){</p> <p>}</p> <p>Base* 将永远和Derived类型不同</p> <p>只有typeid 的操作数是带虚函数的类的对象的时候，才返回动态类型信息，测试指针返回指针的静态的，编译时类型</p> <p>（三 ）type_info 类</p> <p>作为typeid的返回值 提供</p> <p>t1==t2 t1!=t2 t.name() 的操作</p> <p>&nbsp;</p> <p>作为应用例子，可以实现一个类型敏感的相等操作符</p> <p>friend bool operator == (const base&amp; lhs, const base&amp; rhs){</p> <p>&nbsp;&nbsp;&nbsp; return typeid(lhs)==typeid(rhs) &amp;&amp; lhs.equal(rhs);</p> <p>}</p> <p>这样可以处理基类子类混合的相等判断了</p><img src ="http://www.cppblog.com/zqsand/aggbug/104714.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/zqsand/" target="_blank">rikisand</a> 2010-01-03 17:59 <a href="http://www.cppblog.com/zqsand/archive/2010/01/03/104714.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>State 模式</title><link>http://www.cppblog.com/zqsand/archive/2009/12/29/104405.html</link><dc:creator>rikisand</dc:creator><author>rikisand</author><pubDate>Tue, 29 Dec 2009 13:25:00 GMT</pubDate><guid>http://www.cppblog.com/zqsand/archive/2009/12/29/104405.html</guid><wfw:comment>http://www.cppblog.com/zqsand/comments/104405.html</wfw:comment><comments>http://www.cppblog.com/zqsand/archive/2009/12/29/104405.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/zqsand/comments/commentRss/104405.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/zqsand/services/trackbacks/104405.html</trackback:ping><description><![CDATA[

<p><font face="微软雅黑" color="#0080ff" size="4">STATE 模式：</font></p> <p><font face="微软雅黑" color="#0080ff" size="4">一个对象的行为取决于他的状态，而且它必须在运行时根据状态改变他的行为。常规实现中，一个操作含有庞大的多分支的条件语句，且这些分支依赖于该对象的状态。这个状态通常使用一个或者多个枚举常量表示。STate模式把这些状态时候的对象看做一个独立的对象，也就是将不同状态时的行为分散到相应的状态类中。要达到这样的效果，需要context，也就是状态的持有者，即原先的类；抽象状态类，他封装了与context交互的接口；具体状态类，也就是一个个的具体状态。context中保存一个抽象状态类对象为成员，并delegate对象行为给他，从而使相应状态下的行为代码生效。如果状态改变的准则不是固定的则state状态类同时应该重写changestate类以控制状态的改变，否则可以在context中实现。</font></p> <p><font face="微软雅黑" color="#0080ff" size="4">具体到我们的项目：</font></p> <p><font face="微软雅黑" color="#0080ff" size="4">每一个device即为context，他拥有一个state对象，device中的函数processMsg(){state-&gt;processMSg();} 由于状态改变的规则依赖于收到的消息，也就是说一个状态可能转换到多个状态device的每个状态需要重写statechange方法，stateChange(){state-&gt;stateChange(this，msg);} 这样，不同的状态下的行为实现在具体状态的类中，比原先的版本清晰明了，可读性更强。</font></p><img src ="http://www.cppblog.com/zqsand/aggbug/104405.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/zqsand/" target="_blank">rikisand</a> 2009-12-29 21:25 <a href="http://www.cppblog.com/zqsand/archive/2009/12/29/104405.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ALGORITHM IN C (1)</title><link>http://www.cppblog.com/zqsand/archive/2009/11/11/100725.html</link><dc:creator>rikisand</dc:creator><author>rikisand</author><pubDate>Wed, 11 Nov 2009 12:18:00 GMT</pubDate><guid>http://www.cppblog.com/zqsand/archive/2009/11/11/100725.html</guid><wfw:comment>http://www.cppblog.com/zqsand/comments/100725.html</wfw:comment><comments>http://www.cppblog.com/zqsand/archive/2009/11/11/100725.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/zqsand/comments/commentRss/100725.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/zqsand/services/trackbacks/100725.html</trackback:ping><description><![CDATA[
<pre class="code"><font size="4">Steps to developing a usable algorithm.<br>&#8226; Define the problem.<br>&#8226; Find an algorithm to solve it.<br>&#8226; Fast enough?<br>&#8226; If not, figure out why.<br>&#8226; Find a way to address the problem.<br>&#8226; Iterate until satisfied.</font></pre>
<p><font size="4">&nbsp; </font>
</p><p><font size="4">主要内容 FIND-UNION ALGORITHM </font>
</p><p><font size="4">就是利用并查集来考察连通性的算法 。条件N个节点，M对节点，输入每一对节点时候，如果已经连通，则忽略，否则输出接点并更新 </font>
</p><p><font size="4">主要介绍三种算法：第一种，QUCK-FIND 利用数组记录每一个联通子图，同一个联通子图的节点数组变量是相同的。因此每读入一对就需要遍历N个数组变量考察是否需要更新，最坏时间MN，实际上每个子图为高度为2的树;第二种，QUICK-UNION 联通子图需要union时 仅仅需要将两个root union 因此每个联通子图高度变高，所有find root 会消耗一定时间，当然无需遍历N了 ，最坏时间，也就是每次均需要从叶子节点去回溯求根（这里书中举得例子好像有问题）也是MN；第三种也就是 QUICK WEIGHT UNION 这种方法在两个子树合并的时候，不是简单的指定合并策略，而是经过判断的，把size小（相应高度也小）的合并到size大的里面；实际上很容易理解就是尽量减少树的高度来追求quick-find的效率； </font>
</p><p><font size="4">进而作者写道路径压缩，也是这种思想。或者实现为全部压缩，也就是说在进行union操作的时候，所有check的节点都直接链接到union后的新root下面，或者half union （容易实现且性能好）每次check时候，如果没有停止loop简单的令 id[i]=id[id[i]];即可达到减少到根距离的效果。 </font>
</p><p><font size="4">half union 的主要代码：</font></p><pre class="code"><span style="background: #2b2b2b; color: #0080ff"><font size="4">int </font></span><font size="4"><span style="background: #2b2b2b; color: white">i,j;
</span><span style="background: #2b2b2b; color: #0080ff">for</span></font><font size="4"><span style="background: #2b2b2b; color: white">(i=p;id[i]!=i;i=id[i]) id[i]=id[id[i]];
</span><span style="background: #2b2b2b; color: #0080ff">for</span></font><font size="4"><span style="background: #2b2b2b; color: white">(j=p;id[j]!=j;j=id[j]) id[j]=id[id[j]];
</span><span style="background: #2b2b2b; color: #0080ff">if</span><span style="background: #2b2b2b; color: white">(i==j)</span><span style="background: #2b2b2b; color: #0080ff">continue</span></font><font size="4"><span style="background: #2b2b2b; color: white">;
</span><span style="background: #2b2b2b; color: #0080ff">if</span></font><font size="4"><span style="background: #2b2b2b; color: white">(size[i]&gt;size[j]) id[j]=i,size[i]+=size[j];
</span><span style="background: #2b2b2b; color: #0080ff">else        </span><span style="background: #2b2b2b; color: white">id[i]=j,size[j]+=size[i];</span></font></pre><a href="http://11011.net/software/vspaste"></a>
<p><font size="5"></font>&nbsp; </p><p><font size="5">第一次用windows live writer 试试效果哦~~</font> 
</p><p><font size="5"></font>&nbsp; </p><p><font size="5"></font>&nbsp; </p><p><font size="5"></font>&nbsp; </p><p><font size="5"></font>&nbsp; </p><p><font size="5"></font>&nbsp; </p><p><font size="5"></font>&nbsp; </p><p><font size="5"></font>&nbsp; </p><p><font size="5"></font>&nbsp; </p><p><font size="5"></font></p><img src ="http://www.cppblog.com/zqsand/aggbug/100725.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/zqsand/" target="_blank">rikisand</a> 2009-11-11 20:18 <a href="http://www.cppblog.com/zqsand/archive/2009/11/11/100725.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>11.7</title><link>http://www.cppblog.com/zqsand/archive/2009/11/07/100354.html</link><dc:creator>rikisand</dc:creator><author>rikisand</author><pubDate>Sat, 07 Nov 2009 13:18:00 GMT</pubDate><guid>http://www.cppblog.com/zqsand/archive/2009/11/07/100354.html</guid><wfw:comment>http://www.cppblog.com/zqsand/comments/100354.html</wfw:comment><comments>http://www.cppblog.com/zqsand/archive/2009/11/07/100354.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/zqsand/comments/commentRss/100354.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/zqsand/services/trackbacks/100354.html</trackback:ping><description><![CDATA[




<div style="background-color: rgb(238, 238, 238); font-size: 13px; border-left-color: rgb(204, 204, 204); padding-right: 5px; padding-bottom: 4px; padding-left: 4px; padding-top: 4px; width: 98%; word-break: break-all; "><div style="border-left-color: rgb(102, 102, 102); ">what's this</div><div style="border-left-color: rgb(102, 102, 102); ">and<span class="Apple-tab-span" style="white-space:pre">	</span>...</div></div><div style="background-color: rgb(238, 238, 238); font-size: 13px; border-left-color: rgb(204, 204, 204); padding-right: 5px; padding-bottom: 4px; padding-left: 4px; padding-top: 4px; width: 98%; word-break: break-all; ">恩 ，做完了就要写下来 省的之后忘了</div><div style="background-color: rgb(238, 238, 238); font-size: 13px; border-left-color: rgb(204, 204, 204); padding-right: 5px; padding-bottom: 4px; padding-left: 4px; padding-top: 4px; width: 98%; word-break: break-all; ">昨天看的misof的教程 关于数~ 今天做了其中的提到的例题：</div><div style="background-color: rgb(238, 238, 238); font-size: 13px; border-left-color: rgb(204, 204, 204); padding-right: 5px; padding-bottom: 4px; padding-left: 4px; padding-top: 4px; width: 98%; word-break: break-all; ">BorelSe:</div><div style="background-color: rgb(238, 238, 238); font-size: 13px; border-left-color: rgb(204, 204, 204); padding-right: 5px; padding-bottom: 4px; padding-left: 4px; padding-top: 4px; width: 98%; word-break: break-all; "><span class="Apple-tab-span" style="white-space:pre">	</span>simple的题~第一次没搞对，搞完后发现还是写麻烦了。题目中明确说明，也显而易见的是空集和全集一定是B集里的 ，我还费心去处理空集。。。</div><div style="background-color: rgb(238, 238, 238); font-size: 13px; border-left-color: rgb(204, 204, 204); padding-right: 5px; padding-bottom: 4px; padding-left: 4px; padding-top: 4px; width: 98%; word-break: break-all; "><span class="Apple-tab-span" style="white-space:pre">	</span>其次，重复的数字不用处理，因为用的是或操作。</div><div style="background-color: rgb(238, 238, 238); font-size: 13px; border-left-color: rgb(204, 204, 204); padding-right: 5px; padding-bottom: 4px; padding-left: 4px; padding-top: 4px; width: 98%; word-break: break-all; "><span class="Apple-tab-span" style="white-space:pre">	</span>剩下的就是用一个数组和一个set不断循环了，其实用队列效果很好的，恩&#183;&#183;&#183;</div><div style="background-color: rgb(238, 238, 238); font-size: 13px; border-left-color: rgb(204, 204, 204); padding-right: 5px; padding-bottom: 4px; padding-left: 4px; padding-top: 4px; width: 98%; word-break: break-all; "><img id="Code_Closed_Image_210330" onclick="this.style.display='none'; Code_Closed_Text_210330.style.display='none'; Code_Open_Image_210330.style.display='inline'; Code_Open_Text_210330.style.display='inline';" height="16" src="http://www.cppblog.com/images/OutliningIndicators/ContractedBlock.gif" width="11" align="top" style="display: none; "><img id="Code_Open_Image_210330" style="display: inline; " onclick="this.style.display='none'; Code_Open_Text_210330.style.display='none'; Code_Closed_Image_210330.style.display='inline'; Code_Closed_Text_210330.style.display='inline';" height="16" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockStart.gif" width="11" align="top"><span id="Code_Closed_Text_210330" style="border-right-color: rgb(128, 128, 128); border-right-width: 1px; border-right-style: solid; border-top-color: rgb(128, 128, 128); border-top-width: 1px; border-top-style: solid; border-left-color: rgb(128, 128, 128); border-left-width: 1px; border-left-style: solid; border-bottom-color: rgb(128, 128, 128); border-bottom-width: 1px; border-bottom-style: solid; background-color: rgb(255, 255, 255); display: none; ">试试看~tc.BorelSe</span><span id="Code_Open_Text_210330" style="display: inline; "><br><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #008080; ">&nbsp;1</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;howMany(</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;size,&nbsp;vector&nbsp;</span><span style="color: #000000; ">&lt;</span><span style="color: #0000FF; ">string</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">&nbsp;sub)<br></span><span style="color: #008080; ">&nbsp;2</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br></span><span style="color: #008080; ">&nbsp;3</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">set</span><span style="color: #000000; ">&lt;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">&nbsp;q;q.clear();</span><span style="color: #0000FF; ">string</span><span style="color: #000000; ">&nbsp;str;<br></span><span style="color: #008080; ">&nbsp;4</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;mask</span><span style="color: #000000; ">=</span><span style="color: #000000; ">(</span><span style="color: #000000; ">1</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">size)</span><span style="color: #000000; ">-</span><span style="color: #000000; ">1</span><span style="color: #000000; ">;<br></span><span style="color: #008080; ">&nbsp;5</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;VI&nbsp;C;<br></span><span style="color: #008080; ">&nbsp;6</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;REPV(sub,i){<br></span><span style="color: #008080; ">&nbsp;7</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">(sub[i]</span><span style="color: #000000; ">==</span><span style="color: #000000; ">""</span><span style="color: #000000; ">)C.push_back(</span><span style="color: #000000; ">0</span><span style="color: #000000; ">),q.insert(</span><span style="color: #000000; ">0</span><span style="color: #000000; ">);<br></span><span style="color: #008080; ">&nbsp;8</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">else</span><span style="color: #000000; ">{<br></span><span style="color: #008080; ">&nbsp;9</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">set</span><span style="color: #000000; ">&lt;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">&nbsp;vec;<br></span><span style="color: #008080; ">10</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;stringstream&nbsp;ss(sub[i]);str</span><span style="color: #000000; ">=</span><span style="color: #000000; ">""</span><span style="color: #000000; ">;<br></span><span style="color: #008080; ">11</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">while</span><span style="color: #000000; ">(ss</span><span style="color: #000000; ">&gt;&gt;</span><span style="color: #000000; ">str)&nbsp;{<br></span><span style="color: #008080; ">12</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">(str</span><span style="color: #000000; ">==</span><span style="color: #000000; ">""</span><span style="color: #000000; ">)vec.insert(</span><span style="color: #000000; ">0</span><span style="color: #000000; ">);<br></span><span style="color: #008080; ">13</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">else</span><span style="color: #000000; ">&nbsp;vec.insert(atoi(str.c_str())</span><span style="color: #000000; ">-</span><span style="color: #000000; ">1</span><span style="color: #000000; ">);&nbsp;<br></span><span style="color: #008080; ">14</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<br></span><span style="color: #008080; ">15</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br></span><span style="color: #008080; ">16</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;now</span><span style="color: #000000; ">=</span><span style="color: #000000; ">0</span><span style="color: #000000; ">;<br></span><span style="color: #008080; ">17</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">for</span><span style="color: #000000; ">(</span><span style="color: #0000FF; ">set</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;it</span><span style="color: #000000; ">=</span><span style="color: #000000; ">vec.begin();it</span><span style="color: #000000; ">!=</span><span style="color: #000000; ">vec.end();it</span><span style="color: #000000; ">++</span><span style="color: #000000; ">){<br></span><span style="color: #008080; ">18</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;now</span><span style="color: #000000; ">|=</span><span style="color: #000000; ">(</span><span style="color: #000000; ">1</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">(</span><span style="color: #000000; ">*</span><span style="color: #000000; ">it));<br></span><span style="color: #008080; ">19</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br></span><span style="color: #008080; ">20</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">(q.count(now)</span><span style="color: #000000; ">==</span><span style="color: #000000; ">0</span><span style="color: #000000; ">)&nbsp;C.push_back(now),q.insert(now);<br></span><span style="color: #008080; ">21</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<br></span><span style="color: #008080; ">22</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br></span><span style="color: #008080; ">23</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;last</span><span style="color: #000000; ">=</span><span style="color: #000000; ">q.size();<br></span><span style="color: #008080; ">24</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">while</span><span style="color: #000000; ">(</span><span style="color: #0000FF; ">true</span><span style="color: #000000; ">){<br></span><span style="color: #008080; ">25</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;REPV(C,i)&nbsp;<br></span><span style="color: #008080; ">26</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br></span><span style="color: #008080; ">27</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;s</span><span style="color: #000000; ">=</span><span style="color: #000000; ">C[i]</span><span style="color: #000000; ">^</span><span style="color: #000000; ">mask;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">(q.count(s)</span><span style="color: #000000; ">==</span><span style="color: #000000; ">0</span><span style="color: #000000; ">)C.push_back(s),q.insert(s);<br></span><span style="color: #008080; ">28</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;REP(j,i)<br></span><span style="color: #008080; ">29</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br></span><span style="color: #008080; ">30</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;k</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;C[i]</span><span style="color: #000000; ">|</span><span style="color: #000000; ">C[j];<br></span><span style="color: #008080; ">31</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">(q.count(k)</span><span style="color: #000000; ">==</span><span style="color: #000000; ">0</span><span style="color: #000000; ">)C.push_back(k),q.insert(k);<br></span><span style="color: #008080; ">32</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br></span><span style="color: #008080; ">33</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br></span><span style="color: #008080; ">34</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">(last</span><span style="color: #000000; ">==</span><span style="color: #000000; ">q.size())</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;last;<br></span><span style="color: #008080; ">35</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">else</span><span style="color: #000000; ">&nbsp;last</span><span style="color: #000000; ">=</span><span style="color: #000000; ">q.size();<br></span><span style="color: #008080; ">36</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br></span><span style="color: #008080; ">37</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span></div><div style="background-color: rgb(238, 238, 238); font-size: 13px; border-left-color: rgb(204, 204, 204); padding-right: 5px; padding-bottom: 4px; padding-left: 4px; padding-top: 4px; width: 98%; word-break: break-all; ">关于数字：</div><div style="background-color: rgb(238, 238, 238); font-size: 13px; border-left-color: rgb(204, 204, 204); padding-right: 5px; padding-bottom: 4px; padding-left: 4px; padding-top: 4px; width: 98%; word-break: break-all; "><span class="Apple-tab-span" style="white-space:pre">	2的n次方 换算成 10的次<span style="FONT-SIZE: 36pt "></span>方 大概是 n/3 数量级的 也就是说 取 n/3+1 大小就可以了</span></div><div style="background-color: rgb(238, 238, 238); font-size: 13px; border-left-color: rgb(204, 204, 204); padding-right: 5px; padding-bottom: 4px; padding-left: 4px; padding-top: 4px; width: 98%; word-break: break-all; "><span class="Apple-tab-span" style="white-space:pre">	</span>这个是double 的数据</div><font face="Arial, Helvetica, Verdana, sans-serif"><span style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px;"><span style="color: rgb(51, 51, 51); font-size: 12px; line-height: 16px; -webkit-border-horizontal-spacing: 0px; -webkit-border-vertical-spacing: 0px; "><table class="formFrame" width="300" cellpadding="6" cellspacing="2" align="center" style="empty-cells: show; "><tbody><tr class="sidebarTitle" nowrap="nowrap" style="color: rgb(51, 51, 51); font-size: 11px; font-weight: bold; background-color: rgb(204, 204, 204); "><td style="font-family: Arial, Helvetica, Verdana, sans-serif; color: rgb(51, 51, 51); text-decoration: none; line-height: 1.4; font-size: 12px; ">&nbsp;</td><td align="center" style="font-family: Arial, Helvetica, Verdana, sans-serif; color: rgb(51, 51, 51); text-decoration: none; line-height: 1.4; font-size: 12px; ">sign</td><td align="center" style="font-family: Arial, Helvetica, Verdana, sans-serif; color: rgb(51, 51, 51); text-decoration: none; line-height: 1.4; font-size: 12px; ">exponent</td><td align="center" style="font-family: Arial, Helvetica, Verdana, sans-serif; color: rgb(51, 51, 51); text-decoration: none; line-height: 1.4; font-size: 12px; ">mantissa</td></tr><tr class="GAtableText"><td style="font-family: Arial, Helvetica, Verdana, sans-serif; color: rgb(51, 51, 51); text-decoration: none; line-height: 1.4; font-size: 12px; "><strong>single precision</strong></td><td align="center" style="font-family: Arial, Helvetica, Verdana, sans-serif; color: rgb(51, 51, 51); text-decoration: none; line-height: 1.4; font-size: 12px; ">1</td><td align="center" style="font-family: Arial, Helvetica, Verdana, sans-serif; color: rgb(51, 51, 51); text-decoration: none; line-height: 1.4; font-size: 12px; ">8</td><td align="center" style="font-family: Arial, Helvetica, Verdana, sans-serif; color: rgb(51, 51, 51); text-decoration: none; line-height: 1.4; font-size: 12px; ">23</td></tr><tr class="GAtableText"><td style="font-family: Arial, Helvetica, Verdana, sans-serif; color: rgb(51, 51, 51); text-decoration: none; line-height: 1.4; font-size: 12px; "><strong>double precision</strong></td><td align="center" style="font-family: Arial, Helvetica, Verdana, sans-serif; color: rgb(51, 51, 51); text-decoration: none; line-height: 1.4; font-size: 12px; ">1</td><td align="center" style="font-family: Arial, Helvetica, Verdana, sans-serif; color: rgb(51, 51, 51); text-decoration: none; line-height: 1.4; font-size: 12px; ">11</td><td align="center" style="font-family: Arial, Helvetica, Verdana, sans-serif; color: rgb(51, 51, 51); text-decoration: none; line-height: 1.4; font-size: 12px; ">52<br><font color="#000000" face="'Times New Roman'" size="7"><span style="font-size: 32px; line-height: normal; -webkit-border-horizontal-spacing: 0px; -webkit-border-vertical-spacing: 0px;"><font color="#333333" face="Arial, Helvetica, Verdana, sans-serif" size="3"><span style="font-size: 12px; line-height: 16px; -webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px;"><br></span></font></span></font></td></tr></tbody></table><font color="#000000" face="'Times New Roman'" size="6"><span style="font-size: 19px; line-height: normal;">&nbsp;<span class="Apple-tab-span" style="white-space:pre">	</span>&nbsp;&nbsp;&nbsp;</span></font></span></span></font><img src ="http://www.cppblog.com/zqsand/aggbug/100354.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/zqsand/" target="_blank">rikisand</a> 2009-11-07 21:18 <a href="http://www.cppblog.com/zqsand/archive/2009/11/07/100354.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Hello Blog World~~ </title><link>http://www.cppblog.com/zqsand/archive/2009/11/07/100348.html</link><dc:creator>rikisand</dc:creator><author>rikisand</author><pubDate>Sat, 07 Nov 2009 11:27:00 GMT</pubDate><guid>http://www.cppblog.com/zqsand/archive/2009/11/07/100348.html</guid><wfw:comment>http://www.cppblog.com/zqsand/comments/100348.html</wfw:comment><comments>http://www.cppblog.com/zqsand/archive/2009/11/07/100348.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/zqsand/comments/commentRss/100348.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/zqsand/services/trackbacks/100348.html</trackback:ping><description><![CDATA[<div style="background-color: rgb(238, 238, 238); font-size: 13px; border-left-color: rgb(204, 204, 204); padding-right: 5px; padding-bottom: 4px; padding-left: 4px; padding-top: 4px; width: 98%; word-break: break-all; ">呵呵~~ just test</div><div style="background-color: rgb(238, 238, 238); font-size: 13px; border-left-color: rgb(204, 204, 204); padding-right: 5px; padding-bottom: 4px; padding-left: 4px; padding-top: 4px; width: 98%; word-break: break-all; "><br></div><div style="background-color: rgb(238, 238, 238); font-size: 13px; border-left-color: rgb(204, 204, 204); 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>--><span style="color: #000000; ">#include</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></span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;main()<br>{<br>&nbsp;&nbsp;&nbsp;cout</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">hello&nbsp;world~</span><span style="color: #000000; ">"</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">endl;<br>&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/zqsand/aggbug/100348.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/zqsand/" target="_blank">rikisand</a> 2009-11-07 19:27 <a href="http://www.cppblog.com/zqsand/archive/2009/11/07/100348.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>