??xml version="1.0" encoding="utf-8" standalone="yes"?>久久综合亚洲色HEZYO国产,久久久久亚洲av综合波多野结衣 ,久久这里只有精品久久http://www.shnenglu.com/vczh/archive/2014/03/01/205998.html陈梓?vczh)陈梓?vczh)Fri, 28 Feb 2014 16:34:00 GMThttp://www.shnenglu.com/vczh/archive/2014/03/01/205998.htmlhttp://www.shnenglu.com/vczh/comments/205998.htmlhttp://www.shnenglu.com/vczh/archive/2014/03/01/205998.html#Feedback1http://www.shnenglu.com/vczh/comments/commentRss/205998.htmlhttp://www.shnenglu.com/vczh/services/trackbacks/205998.html最q学?fn)C++11的variadic template argumentQ终于可以摆qfpmacro模板来复制一大堆代码的做法了Q好开心。这个例子的main函数用lambda写了一个斐波那契数列的递归计算函数。跟以往不同的是Q在Y函数的帮助下Q这个lambda表达是可以成功看到自己,然后递归调用。当然这仍然需要用普通的C++递归来实玎ͼq不是?calculus那个高大上的Y Combinator?

 

#include <functional>

#include <memory>

#include <iostream>

#include <string>

 

using namespace std;

 

template<typename TResult, typename ...TArgs>

class YBuilder

{

private:

    function<TResult(function<TResult(TArgs...)>, TArgs...)> partialLambda;

 

public:

    YBuilder(function<TResult(function<TResult(TArgs...)>, TArgs...)> _partialLambda)

        :partialLambda(_partialLambda)

    {

    }

 

    TResult operator()(TArgs ...args)const

    {

        return partialLambda(

            [this](TArgs ...args)

            {

                return this->operator()(args...);

            }, args...);

    }

};

 

template<typename TMethod>

struct PartialLambdaTypeRetriver

{

    typedef void FunctionType;

    typedef void LambdaType;

    typedef void YBuilderType;

};

 

template<typename TClass, typename TResult, typename ...TArgs>

struct PartialLambdaTypeRetriver<TResult(__thiscall TClass::*)(function<TResult(TArgs...)>, TArgs...)>

{

    typedef TResult FunctionType(TArgs...);

    typedef TResult LambdaType(function<TResult(TArgs...)>, TArgs...);

    typedef YBuilder<TResult, TArgs...> YBuilderType;

};

 

template<typename TClass, typename TResult, typename ...TArgs>

struct PartialLambdaTypeRetriver<TResult(__thiscall TClass::*)(function<TResult(TArgs...)>, TArgs...)const>

{

    typedef TResult FunctionType(TArgs...);

    typedef TResult LambdaType(function<TResult(TArgs...)>, TArgs...);

    typedef YBuilder<TResult, TArgs...> YBuilderType;

};

 

template<typename TLambda>

function<typename PartialLambdaTypeRetriver<decltype(&TLambda::operator())>::FunctionType> Y(TLambda partialLambda)

{

    return typename PartialLambdaTypeRetriver<decltype(&TLambda::operator())>::YBuilderType(partialLambda);

}

 

int _tmain(int argc, _TCHAR* argv[])

{

    auto fib = Y([](function<int(int)> self, int index)

    {

        return index<2

            ?1

            :self(index-1)+self(index-2);

    });

 

    for (int i = 0; i < 10; i++)

    {

        cout << fib(i) << " ";

    }

    cout << endl;

}



陈梓?vczh) 2014-03-01 00:34 发表评论
]]>
C++实用技巧之配置Visual C++的调试器昄数据l构的格式(附Vczh Library++配置文gQ?/title><link>http://www.shnenglu.com/vczh/archive/2013/03/21/198665.html</link><dc:creator>陈梓?vczh)</dc:creator><author>陈梓?vczh)</author><pubDate>Thu, 21 Mar 2013 03:55:00 GMT</pubDate><guid>http://www.shnenglu.com/vczh/archive/2013/03/21/198665.html</guid><wfw:comment>http://www.shnenglu.com/vczh/comments/198665.html</wfw:comment><comments>http://www.shnenglu.com/vczh/archive/2013/03/21/198665.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.shnenglu.com/vczh/comments/commentRss/198665.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/vczh/services/trackbacks/198665.html</trackback:ping><description><![CDATA[<p>今天我写了一个给Visual C++用的配置Q用来让VC++在显C己写的字W串和容器等设施变得跟显CSTL一h亮。VC++的可配置型还是很高的Q我们只要写一个xmlQ就可以改变调试器对自己的数据结构的昄?</p> <p>在这里我单地介绍一下用法。假讑֤家觉得vlppQVczh Library++Q也是GacUI用的那个库)的WString啊Listq些东西在调试器里面昄出来的东西太丑,可以用以下三步来修改它?/p> <p>1Q去<a title="http://gac.codeplex.com/SourceControl/changeset/view/99419#2395529" >http://gac.codeplex.com/SourceControl/changeset/view/99419#2395529</a>下蝲我写的那个natvis文g。这个文件在整个zip包里面的位置是Common\vlpp.natvis<br />2Q把q个文g复制到C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\Packages\Debugger\VisualizersQ如果用默认安装\径的话)<br />3Q重启你最喜爱的Visual Studio 2012Q就可以看到下面的东西了Q?/p> <p><a href="http://www.shnenglu.com/images/cppblog_com/vczh/Windows-Live-Writer/51783bf28f3a_A413/image_2.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.shnenglu.com/images/cppblog_com/vczh/Windows-Live-Writer/51783bf28f3a_A413/image_thumb.png" width="275" height="95" /></a><br />I的指针</p> <p><a href="http://www.shnenglu.com/images/cppblog_com/vczh/Windows-Live-Writer/51783bf28f3a_A413/image_4.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.shnenglu.com/images/cppblog_com/vczh/Windows-Live-Writer/51783bf28f3a_A413/image_thumb_1.png" width="433" height="115" /></a><br />有东西的指针</p> <p><a href="http://www.shnenglu.com/images/cppblog_com/vczh/Windows-Live-Writer/51783bf28f3a_A413/image_6.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.shnenglu.com/images/cppblog_com/vczh/Windows-Live-Writer/51783bf28f3a_A413/image_thumb_2.png" width="224" height="64" /></a><br />有内容的“惰性计?#8221;c?/p> <p><a href="http://www.shnenglu.com/images/cppblog_com/vczh/Windows-Live-Writer/51783bf28f3a_A413/image_8.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.shnenglu.com/images/cppblog_com/vczh/Windows-Live-Writer/51783bf28f3a_A413/image_thumb_3.png" width="344" height="88" /></a><br />有内容但是还没计的“惰性计?#8221;c?/p> <p><a href="http://www.shnenglu.com/images/cppblog_com/vczh/Windows-Live-Writer/51783bf28f3a_A413/image_10.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.shnenglu.com/images/cppblog_com/vczh/Windows-Live-Writer/51783bf28f3a_A413/image_thumb_4.png" width="353" height="83" /></a><br />没内容的“惰性计?#8221;c?/p> <p><a href="http://www.shnenglu.com/images/cppblog_com/vczh/Windows-Live-Writer/51783bf28f3a_A413/image_12.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.shnenglu.com/images/cppblog_com/vczh/Windows-Live-Writer/51783bf28f3a_A413/image_thumb_5.png" width="445" height="259" /></a><br />新鲜热G的容?/p> <p><a href="http://www.shnenglu.com/images/cppblog_com/vczh/Windows-Live-Writer/51783bf28f3a_A413/image_14.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.shnenglu.com/images/cppblog_com/vczh/Windows-Live-Writer/51783bf28f3a_A413/image_thumb_6.png" width="667" height="226" /></a><br />新鲜热G的映?/p> <p><a href="http://www.shnenglu.com/images/cppblog_com/vczh/Windows-Live-Writer/51783bf28f3a_A413/image_16.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.shnenglu.com/images/cppblog_com/vczh/Windows-Live-Writer/51783bf28f3a_A413/image_thumb_7.png" width="596" height="295" /></a><br />p一对多的映也是如此的新鲜热G</p> <p><a href="http://www.shnenglu.com/images/cppblog_com/vczh/Windows-Live-Writer/51783bf28f3a_A413/image_18.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.shnenglu.com/images/cppblog_com/vczh/Windows-Live-Writer/51783bf28f3a_A413/image_thumb_8.png" width="318" height="161" /></a><br />List<Nullable<vint>>的互相嵌套也是如此的完美</p> <p>如果大家惛_自己的Customized Visualizer的话Q可以去参考微软良心提供的文档<a title="http://msdn.microsoft.com/en-us/library/vstudio/jj620914.aspx" >http://msdn.microsoft.com/en-us/library/vstudio/jj620914.aspx</a>Q然后按照上面的步骤写自qnatvis文g。在q里我把我的natvis贴上来,以供参考:(x)</p> <div style="border-bottom: #cccccc 1px solid; border-left: #cccccc 1px solid; padding-bottom: 5px; background-color: #f5f5f5; padding-left: 5px; padding-right: 5px; border-top: #cccccc 1px solid; border-right: #cccccc 1px solid; padding-top: 5px" class="cnblogs_code"><pre><span style="color: #0000ff"><?</span><span style="color: #ff00ff">xml version="1.0" encoding="utf-8"</span><span style="color: #0000ff">?></span> <span style="color: #0000ff"><</span><span style="color: #800000">AutoVisualizer </span><span style="color: #ff0000">xmlns</span><span style="color: #0000ff">="http://schemas.microsoft.com/vstudio/debugger/natvis/2010"</span><span style="color: #0000ff">></span> <span style="color: #0000ff"><</span><span style="color: #800000">Type </span><span style="color: #ff0000">Name</span><span style="color: #0000ff">="vl::ObjectString&lt;wchar_t&gt;"</span><span style="color: #0000ff">></span> <span style="color: #0000ff"><</span><span style="color: #800000">DisplayString</span><span style="color: #0000ff">></span>{{ size={length}, buffer={buffer+start,su} }}<span style="color: #0000ff"></</span><span style="color: #800000">DisplayString</span><span style="color: #0000ff">></span> <span style="color: #0000ff"><</span><span style="color: #800000">StringView</span><span style="color: #0000ff">></span>buffer+start,su<span style="color: #0000ff"></</span><span style="color: #800000">StringView</span><span style="color: #0000ff">></span> <span style="color: #0000ff"><</span><span style="color: #800000">Expand</span><span style="color: #0000ff">></span> <span style="color: #0000ff"><</span><span style="color: #800000">Item </span><span style="color: #ff0000">Name</span><span style="color: #0000ff">="[size]"</span><span style="color: #0000ff">></span>length<span style="color: #0000ff"></</span><span style="color: #800000">Item</span><span style="color: #0000ff">></span> <span style="color: #0000ff"><</span><span style="color: #800000">ArrayItems</span><span style="color: #0000ff">></span> <span style="color: #0000ff"><</span><span style="color: #800000">Size</span><span style="color: #0000ff">></span>length<span style="color: #0000ff"></</span><span style="color: #800000">Size</span><span style="color: #0000ff">></span> <span style="color: #0000ff"><</span><span style="color: #800000">ValuePointer</span><span style="color: #0000ff">></span>buffer+start<span style="color: #0000ff"></</span><span style="color: #800000">ValuePointer</span><span style="color: #0000ff">></span> <span style="color: #0000ff"></</span><span style="color: #800000">ArrayItems</span><span style="color: #0000ff">></span> <span style="color: #0000ff"></</span><span style="color: #800000">Expand</span><span style="color: #0000ff">></span> <span style="color: #0000ff"></</span><span style="color: #800000">Type</span><span style="color: #0000ff">></span> <span style="color: #0000ff"><</span><span style="color: #800000">Type </span><span style="color: #ff0000">Name</span><span style="color: #0000ff">="vl::ObjectString&lt;char&gt;"</span><span style="color: #0000ff">></span> <span style="color: #0000ff"><</span><span style="color: #800000">DisplayString</span><span style="color: #0000ff">></span>{{ size={length}, buffer={buffer+start,s} }}<span style="color: #0000ff"></</span><span style="color: #800000">DisplayString</span><span style="color: #0000ff">></span> <span style="color: #0000ff"><</span><span style="color: #800000">StringView</span><span style="color: #0000ff">></span>buffer+start,s<span style="color: #0000ff"></</span><span style="color: #800000">StringView</span><span style="color: #0000ff">></span> <span style="color: #0000ff"><</span><span style="color: #800000">Expand</span><span style="color: #0000ff">></span> <span style="color: #0000ff"><</span><span style="color: #800000">Item </span><span style="color: #ff0000">Name</span><span style="color: #0000ff">="[size]"</span><span style="color: #0000ff">></span>length<span style="color: #0000ff"></</span><span style="color: #800000">Item</span><span style="color: #0000ff">></span> <span style="color: #0000ff"><</span><span style="color: #800000">ArrayItems</span><span style="color: #0000ff">></span> <span style="color: #0000ff"><</span><span style="color: #800000">Size</span><span style="color: #0000ff">></span>length<span style="color: #0000ff"></</span><span style="color: #800000">Size</span><span style="color: #0000ff">></span> <span style="color: #0000ff"><</span><span style="color: #800000">ValuePointer</span><span style="color: #0000ff">></span>buffer+start<span style="color: #0000ff"></</span><span style="color: #800000">ValuePointer</span><span style="color: #0000ff">></span> <span style="color: #0000ff"></</span><span style="color: #800000">ArrayItems</span><span style="color: #0000ff">></span> <span style="color: #0000ff"></</span><span style="color: #800000">Expand</span><span style="color: #0000ff">></span> <span style="color: #0000ff"></</span><span style="color: #800000">Type</span><span style="color: #0000ff">></span> <span style="color: #0000ff"><</span><span style="color: #800000">Type </span><span style="color: #ff0000">Name</span><span style="color: #0000ff">="vl::collections::List&lt;*,*&gt;"</span><span style="color: #0000ff">></span> <span style="color: #0000ff"><</span><span style="color: #800000">AlternativeType </span><span style="color: #ff0000">Name</span><span style="color: #0000ff">="vl::collections::SortedList&lt;*,*&gt;"</span><span style="color: #0000ff">/></span> <span style="color: #0000ff"><</span><span style="color: #800000">AlternativeType </span><span style="color: #ff0000">Name</span><span style="color: #0000ff">="vl::collections::Array&lt;*,*&gt;"</span><span style="color: #0000ff">/></span> <span style="color: #0000ff"><</span><span style="color: #800000">DisplayString</span><span style="color: #0000ff">></span>{{ size={count} }}<span style="color: #0000ff"></</span><span style="color: #800000">DisplayString</span><span style="color: #0000ff">></span> <span style="color: #0000ff"><</span><span style="color: #800000">Expand</span><span style="color: #0000ff">></span> <span style="color: #0000ff"><</span><span style="color: #800000">Item </span><span style="color: #ff0000">Name</span><span style="color: #0000ff">="[size]"</span><span style="color: #0000ff">></span>count<span style="color: #0000ff"></</span><span style="color: #800000">Item</span><span style="color: #0000ff">></span> <span style="color: #0000ff"><</span><span style="color: #800000">ArrayItems</span><span style="color: #0000ff">></span> <span style="color: #0000ff"><</span><span style="color: #800000">Size</span><span style="color: #0000ff">></span>count<span style="color: #0000ff"></</span><span style="color: #800000">Size</span><span style="color: #0000ff">></span> <span style="color: #0000ff"><</span><span style="color: #800000">ValuePointer</span><span style="color: #0000ff">></span>buffer<span style="color: #0000ff"></</span><span style="color: #800000">ValuePointer</span><span style="color: #0000ff">></span> <span style="color: #0000ff"></</span><span style="color: #800000">ArrayItems</span><span style="color: #0000ff">></span> <span style="color: #0000ff"></</span><span style="color: #800000">Expand</span><span style="color: #0000ff">></span> <span style="color: #0000ff"></</span><span style="color: #800000">Type</span><span style="color: #0000ff">></span> <span style="color: #0000ff"><</span><span style="color: #800000">Type </span><span style="color: #ff0000">Name</span><span style="color: #0000ff">="vl::collections::Dictionary&lt;*,*,*,*&gt;"</span><span style="color: #0000ff">></span> <span style="color: #0000ff"><</span><span style="color: #800000">AlternativeType </span><span style="color: #ff0000">Name</span><span style="color: #0000ff">="vl::collections::Group&lt;*,*,*,*&gt;"</span><span style="color: #0000ff">/></span> <span style="color: #0000ff"><</span><span style="color: #800000">DisplayString</span><span style="color: #0000ff">></span>{{ size={keys.count} }}<span style="color: #0000ff"></</span><span style="color: #800000">DisplayString</span><span style="color: #0000ff">></span> <span style="color: #0000ff"><</span><span style="color: #800000">Expand</span><span style="color: #0000ff">></span> <span style="color: #0000ff"><</span><span style="color: #800000">Item </span><span style="color: #ff0000">Name</span><span style="color: #0000ff">="[size]"</span><span style="color: #0000ff">></span>keys.count<span style="color: #0000ff"></</span><span style="color: #800000">Item</span><span style="color: #0000ff">></span> <span style="color: #0000ff"><</span><span style="color: #800000">Item </span><span style="color: #ff0000">Name</span><span style="color: #0000ff">="Keys"</span><span style="color: #0000ff">></span>keys<span style="color: #0000ff"></</span><span style="color: #800000">Item</span><span style="color: #0000ff">></span> <span style="color: #0000ff"><</span><span style="color: #800000">Item </span><span style="color: #ff0000">Name</span><span style="color: #0000ff">="Values"</span><span style="color: #0000ff">></span>values<span style="color: #0000ff"></</span><span style="color: #800000">Item</span><span style="color: #0000ff">></span> <span style="color: #0000ff"></</span><span style="color: #800000">Expand</span><span style="color: #0000ff">></span> <span style="color: #0000ff"></</span><span style="color: #800000">Type</span><span style="color: #0000ff">></span> <span style="color: #0000ff"><</span><span style="color: #800000">Type </span><span style="color: #ff0000">Name</span><span style="color: #0000ff">="vl::Ptr&lt;*&gt;"</span><span style="color: #0000ff">></span> <span style="color: #0000ff"><</span><span style="color: #800000">AlternativeType </span><span style="color: #ff0000">Name</span><span style="color: #0000ff">="vl::ComPtr&lt;*&gt;"</span><span style="color: #0000ff">/></span> <span style="color: #0000ff"><</span><span style="color: #800000">DisplayString </span><span style="color: #ff0000">Condition</span><span style="color: #0000ff">="reference == 0"</span><span style="color: #0000ff">></span>[empty]<span style="color: #0000ff"></</span><span style="color: #800000">DisplayString</span><span style="color: #0000ff">></span> <span style="color: #0000ff"><</span><span style="color: #800000">DisplayString </span><span style="color: #ff0000">Condition</span><span style="color: #0000ff">="reference != 0"</span><span style="color: #0000ff">></span>{*reference}<span style="color: #0000ff"></</span><span style="color: #800000">DisplayString</span><span style="color: #0000ff">></span> <span style="color: #0000ff"><</span><span style="color: #800000">Expand</span><span style="color: #0000ff">></span> <span style="color: #0000ff"><</span><span style="color: #800000">Item </span><span style="color: #ff0000">Condition</span><span style="color: #0000ff">="reference != 0"</span><span style="color: #ff0000"> Name</span><span style="color: #0000ff">="[ptr]"</span><span style="color: #0000ff">></span>reference<span style="color: #0000ff"></</span><span style="color: #800000">Item</span><span style="color: #0000ff">></span> <span style="color: #0000ff"></</span><span style="color: #800000">Expand</span><span style="color: #0000ff">></span> <span style="color: #0000ff"></</span><span style="color: #800000">Type</span><span style="color: #0000ff">></span> <span style="color: #0000ff"><</span><span style="color: #800000">Type </span><span style="color: #ff0000">Name</span><span style="color: #0000ff">="vl::Lazy&lt;*&gt;"</span><span style="color: #0000ff">></span> <span style="color: #0000ff"><</span><span style="color: #800000">DisplayString </span><span style="color: #ff0000">Condition</span><span style="color: #0000ff">="internalValue.reference == 0"</span><span style="color: #0000ff">></span>[empty]<span style="color: #0000ff"></</span><span style="color: #800000">DisplayString</span><span style="color: #0000ff">></span> <span style="color: #0000ff"><</span><span style="color: #800000">DisplayString </span><span style="color: #ff0000">Condition</span><span style="color: #0000ff">="internalValue.reference != 0 &amp;&amp; internalValue.reference->evaluated == false"</span><span style="color: #0000ff">></span>[not evaluated]<span style="color: #0000ff"></</span><span style="color: #800000">DisplayString</span><span style="color: #0000ff">></span> <span style="color: #0000ff"><</span><span style="color: #800000">DisplayString </span><span style="color: #ff0000">Condition</span><span style="color: #0000ff">="internalValue.reference != 0 &amp;&amp; internalValue.reference->evaluated == true"</span><span style="color: #0000ff">></span>{internalValue.reference->value}<span style="color: #0000ff"></</span><span style="color: #800000">DisplayString</span><span style="color: #0000ff">></span> <span style="color: #0000ff"><</span><span style="color: #800000">Expand</span><span style="color: #0000ff">></span> <span style="color: #0000ff"><</span><span style="color: #800000">Item </span><span style="color: #ff0000">Condition</span><span style="color: #0000ff">="internalValue.reference != 0 &amp;&amp; internalValue.reference->evaluated == true"</span><span style="color: #ff0000"> Name</span><span style="color: #0000ff">="[value]"</span><span style="color: #0000ff">></span>internalValue.reference->value<span style="color: #0000ff"></</span><span style="color: #800000">Item</span><span style="color: #0000ff">></span> <span style="color: #0000ff"></</span><span style="color: #800000">Expand</span><span style="color: #0000ff">></span> <span style="color: #0000ff"></</span><span style="color: #800000">Type</span><span style="color: #0000ff">></span> <span style="color: #0000ff"><</span><span style="color: #800000">Type </span><span style="color: #ff0000">Name</span><span style="color: #0000ff">="vl::ObjectBox&lt;*&gt;"</span><span style="color: #0000ff">></span> <span style="color: #0000ff"><</span><span style="color: #800000">DisplayString</span><span style="color: #0000ff">></span>{object}<span style="color: #0000ff"></</span><span style="color: #800000">DisplayString</span><span style="color: #0000ff">></span> <span style="color: #0000ff"><</span><span style="color: #800000">Expand</span><span style="color: #0000ff">></span> <span style="color: #0000ff"><</span><span style="color: #800000">ExpandedItem</span><span style="color: #0000ff">></span>object<span style="color: #0000ff"></</span><span style="color: #800000">ExpandedItem</span><span style="color: #0000ff">></span> <span style="color: #0000ff"></</span><span style="color: #800000">Expand</span><span style="color: #0000ff">></span> <span style="color: #0000ff"></</span><span style="color: #800000">Type</span><span style="color: #0000ff">></span> <span style="color: #0000ff"><</span><span style="color: #800000">Type </span><span style="color: #ff0000">Name</span><span style="color: #0000ff">="vl::Nullable&lt;*&gt;"</span><span style="color: #0000ff">></span> <span style="color: #0000ff"><</span><span style="color: #800000">DisplayString </span><span style="color: #ff0000">Condition</span><span style="color: #0000ff">="object == 0"</span><span style="color: #0000ff">></span>[empty]<span style="color: #0000ff"></</span><span style="color: #800000">DisplayString</span><span style="color: #0000ff">></span> <span style="color: #0000ff"><</span><span style="color: #800000">DisplayString </span><span style="color: #ff0000">Condition</span><span style="color: #0000ff">="object != 0"</span><span style="color: #0000ff">></span>{*object}<span style="color: #0000ff"></</span><span style="color: #800000">DisplayString</span><span style="color: #0000ff">></span> <span style="color: #0000ff"><</span><span style="color: #800000">Expand</span><span style="color: #0000ff">></span> <span style="color: #0000ff"><</span><span style="color: #800000">ExpandedItem </span><span style="color: #ff0000">Condition</span><span style="color: #0000ff">="object != 0"</span><span style="color: #0000ff">></span>*object<span style="color: #0000ff"></</span><span style="color: #800000">ExpandedItem</span><span style="color: #0000ff">></span> <span style="color: #0000ff"></</span><span style="color: #800000">Expand</span><span style="color: #0000ff">></span> <span style="color: #0000ff"></</span><span style="color: #800000">Type</span><span style="color: #0000ff">></span> <span style="color: #0000ff"></</span><span style="color: #800000">AutoVisualizer</span><span style="color: #0000ff">></span></pre></div><img src ="http://www.shnenglu.com/vczh/aggbug/198665.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/vczh/" target="_blank">陈梓?vczh)</a> 2013-03-21 11:55 <a href="http://www.shnenglu.com/vczh/archive/2013/03/21/198665.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用VisualStudio完成自动化C++代码生成和编译工作(GacUIQ?/title><link>http://www.shnenglu.com/vczh/archive/2012/01/14/164167.html</link><dc:creator>陈梓?vczh)</dc:creator><author>陈梓?vczh)</author><pubDate>Sat, 14 Jan 2012 06:09:00 GMT</pubDate><guid>http://www.shnenglu.com/vczh/archive/2012/01/14/164167.html</guid><wfw:comment>http://www.shnenglu.com/vczh/comments/164167.html</wfw:comment><comments>http://www.shnenglu.com/vczh/archive/2012/01/14/164167.html#Feedback</comments><slash:comments>7</slash:comments><wfw:commentRss>http://www.shnenglu.com/vczh/comments/commentRss/164167.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/vczh/services/trackbacks/164167.html</trackback:ping><description><![CDATA[<div>    GacUIl于q入制作dll的阶D了。昨天上传了一个新的工E,?a style="text-decoration: underline" target="_blank">Vczh Library++3.0</a>QE:\Codeplex\vlpp\Workspace\Tools\Release\SideProjects\GacUI\GacUI.slnQ。这里面一共有三个工程Q有两个是工P一个是dll?br /><br />    Z~译出带反射的控件库Q因此每一个控仉可以获得一个ITypeDescriptor对象。但是控件库一共有几十个类上千个函敎ͼ我不可能一个一个去实现的(h惛_现IDispatcher的时候)。根?a style="text-decoration: underline" href="http://www.shnenglu.com/vczh/archive/2012/01/11/164003.html" target="_blank">上一博?/a>讨论q技术,我将使用一个程序来读pdb生成C++代码。详l的计划如下Q?br /><br />    1Q制作一个_GacPDB工程。这是一个exeQ但是是没用的,唯一的用处就是他引用了GacUI.dll所需要的所有源代码Q然后靠~译器生PDB文g?br />    2Q制作一个_TranslatePDBtoXML工程。这是一个exeQ从PDB抽取cd明?br />    3Q制作一个_TranslateXMltoCode。顾名思义Q不q现在还没做Q原理是一L(fng)?br />    4QGacUI.dll。这个dll包含了所有的控g的实玎ͼq有_TranslateXMLtoCode产生的所有代码?br /><br />    现在我的目标是,先编译_Translate*工程Q然后编译_GacPDB产生pdb后自动调用它们,生成代码l束之后开始合q编译GacUI.dll。所有的q些东西都需要在VisualStudio?#8220;Rebuild Solution”里面完成。ؓ(f)了完成这个目标,我创些工E之后,按照下面的方法修改了工程属性:(x) <div style="border-bottom: #cccccc 1px solid; border-left: #cccccc 1px solid; padding-bottom: 4px; background-color: #eeeeee; padding-left: 4px; width: 98%; padding-right: 5px; font-size: 13px; word-break: break-all; border-top: #cccccc 1px solid; border-right: #cccccc 1px solid; padding-top: 4px"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008080"> 1</span> <span style="color: #000000">_TranslatePDBtoXML:<br /></span><span style="color: #008080"> 2</span> <span style="color: #000000">    post build action:<br /></span><span style="color: #008080"> 3</span> <span style="color: #000000">        copy $(ProjectDir)msdia100.dll $(SolutionDir)$(Configuration)\msdia100.dll<br /></span><span style="color: #008080"> 4</span> <span style="color: #000000">_GenPDB:<br /></span><span style="color: #008080"> 5</span> <span style="color: #000000">    references:<br /></span><span style="color: #008080"> 6</span> <span style="color: #000000">        _TranslatePDBtoXML<br /></span><span style="color: #008080"> 7</span> <span style="color: #000000">    post build action:<br /></span><span style="color: #008080"> 8</span> <span style="color: #000000">        $(SolutionDir)$(Configuration)\_TranslatePDBtoXML.exe $(SolutionDir)Debug\_GenPDB.pdb $(SolutionDir)_GenPDB.xml<br /></span><span style="color: #008080"> 9</span> <span style="color: #000000">GacUI:<br /></span><span style="color: #008080">10</span> <span style="color: #000000">    references:<br /></span><span style="color: #008080">11</span> <span style="color: #000000">        _GenPDB</span></div><br />    1Q工EA引用了工EB的话Q那么只有当B完全~译好之后才?x)编译A。因此上面的配置阻止三个工E^行编译,强制他们按照_TranslatePDBtoXML、_GenPDB和GacUI的顺序来?br />    2Q_TranslatePDBtoXML~译好之后,?x)把它依赖的msdia100.dll复制到编译出来的exe旁边Q以供接下来调用?br />    3Q_GenPDB~译好之后,pdb已经产生了。这个时候它?x)自动调用上一步编译出来的_TranslatePDBtoXMLQ读取pdbQ输出xml<br />    4Q(接下来要做的Q调用_TranslateXMLtoCodeQ输入xmlQ输出C++代码<br />    5Q这个时候,生成的C++代码已经qA了,所以开始编译GacUI?br /><br />    附加的好处还有一个。因为_GenPDB引用了GacUI的cppQ所以当GacUI的源代码修改的时候,_GenPDB也会(x)感应刎ͼ从而在下次~译GacUI的时候先开始编译_GenPDB。ƈ且因为GacUI依赖了_GenPDBQ所以_GenPDB仍然?x)先~译。而且q种依赖关系是无害的Q因为_GenPDB没有输出libQ因此GacUI.dll在运行的时候完全不需要_GenPDB.exe的存在?br /><br />    好了。那把一个个的cpp文gd到_GenPDB也是在太ȝ了,所以我投机取y了一下:(x) <div style="border-bottom: #cccccc 1px solid; border-left: #cccccc 1px solid; padding-bottom: 4px; background-color: #eeeeee; padding-left: 4px; width: 98%; padding-right: 5px; font-size: 13px; word-break: break-all; border-top: #cccccc 1px solid; border-right: #cccccc 1px solid; padding-top: 4px"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008080"> 1</span> <span style="color: #000000">#include </span><span style="color: #000000">"</span><span style="color: #000000">..\..\..\..\..\Candidate\GUI\GUI\Controls\GuiApplication.cpp</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080"> 2</span> <span style="color: #000000">#include </span><span style="color: #000000">"</span><span style="color: #000000">..\..\..\..\..\Candidate\GUI\GUI\Controls\GuiBasicControls.cpp</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080"> 3</span> <span style="color: #000000">#include </span><span style="color: #000000">"</span><span style="color: #000000">..\..\..\..\..\Candidate\GUI\GUI\Controls\GuiListControls.cpp</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080"> 4</span> <span style="color: #000000">#include </span><span style="color: #000000">"</span><span style="color: #000000">..\..\..\..\..\Candidate\GUI\GUI\Controls\GuiTextControls.cpp</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080"> 5</span> <span style="color: #000000">#include </span><span style="color: #000000">"</span><span style="color: #000000">..\..\..\..\..\Candidate\GUI\GUI\Controls\GuiWindowControls.cpp</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080"> 6</span> <span style="color: #000000"></span><span style="color: #008000">//</span><span style="color: #008000">---------------------------------------------------------------</span><span style="color: #008000"><br /></span><span style="color: #008080"> 7</span> <span style="color: #008000"></span><span style="color: #000000">#include </span><span style="color: #000000">"</span><span style="color: #000000">..\..\..\..\..\Candidate\GUI\GUI\Controls\ExtendedControls\GuiComboControls.cpp</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080"> 8</span> <span style="color: #000000">#include </span><span style="color: #000000">"</span><span style="color: #000000">..\..\..\..\..\Candidate\GUI\GUI\Controls\ExtendedControls\GuiContainerControls.cpp</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080"> 9</span> <span style="color: #000000">#include </span><span style="color: #000000">"</span><span style="color: #000000">..\..\..\..\..\Candidate\GUI\GUI\Controls\ExtendedControls\GuiListViewControls.cpp</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">10</span> <span style="color: #000000">#include </span><span style="color: #000000">"</span><span style="color: #000000">..\..\..\..\..\Candidate\GUI\GUI\Controls\ExtendedControls\GuiMenuControls.cpp</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">11</span> <span style="color: #000000">#include </span><span style="color: #000000">"</span><span style="color: #000000">..\..\..\..\..\Candidate\GUI\GUI\Controls\ExtendedControls\GuiTextListControls.cpp</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">12</span> <span style="color: #000000">#include </span><span style="color: #000000">"</span><span style="color: #000000">..\..\..\..\..\Candidate\GUI\GUI\Controls\ExtendedControls\GuiTreeViewControls.cpp</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">13</span> <span style="color: #000000"></span><span style="color: #008000">//</span><span style="color: #008000">---------------------------------------------------------------</span><span style="color: #008000"><br /></span><span style="color: #008080">14</span> <span style="color: #008000"></span><span style="color: #000000">#include </span><span style="color: #000000">"</span><span style="color: #000000">..\..\..\..\..\Candidate\GUI\GUI\Controls\Styles\GuiCommonStyles.cpp</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">15</span> <span style="color: #000000">#include </span><span style="color: #000000">"</span><span style="color: #000000">..\..\..\..\..\Candidate\GUI\GUI\Controls\Styles\GuiWin7Styles.cpp</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">16</span> <span style="color: #000000"></span><span style="color: #008000">//</span><span style="color: #008000">---------------------------------------------------------------</span><span style="color: #008000"><br /></span><span style="color: #008080">17</span> <span style="color: #008000"></span><span style="color: #000000">#include </span><span style="color: #000000">"</span><span style="color: #000000">..\..\..\..\..\Candidate\GUI\GUI\GraphicsElement\GuiGraphicsComposition.cpp</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">18</span> <span style="color: #000000">#include </span><span style="color: #000000">"</span><span style="color: #000000">..\..\..\..\..\Candidate\GUI\GUI\GraphicsElement\GuiGraphicsElement.cpp</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">19</span> <span style="color: #000000">#include </span><span style="color: #000000">"</span><span style="color: #000000">..\..\..\..\..\Candidate\GUI\GUI\GraphicsElement\GuiGraphicsEventReceiver.cpp</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">20</span> <span style="color: #000000">#include </span><span style="color: #000000">"</span><span style="color: #000000">..\..\..\..\..\Candidate\GUI\GUI\GraphicsElement\GuiGraphicsHost.cpp</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">21</span> <span style="color: #000000">#include </span><span style="color: #000000">"</span><span style="color: #000000">..\..\..\..\..\Candidate\GUI\GUI\GraphicsElement\GuiGraphicsTextElement.cpp</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">22</span> <span style="color: #000000"></span><span style="color: #008000">//</span><span style="color: #008000">---------------------------------------------------------------</span><span style="color: #008000"><br /></span><span style="color: #008080">23</span> <span style="color: #008000"></span><span style="color: #000000">#include </span><span style="color: #000000">"</span><span style="color: #000000">..\..\..\..\..\Candidate\GUI\GUI\NativeWindow\GuiNativeWindow.cpp</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">24</span> <span style="color: #000000">#include </span><span style="color: #000000">"</span><span style="color: #000000">..\..\..\..\..\Candidate\GUI\GUI\NativeWindow\Windows\WinNativeWindow.cpp</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">25</span> <span style="color: #000000"></span><span style="color: #008000">//</span><span style="color: #008000">---------------------------------------------------------------</span><span style="color: #008000"><br /></span><span style="color: #008080">26</span> <span style="color: #008000"></span><span style="color: #000000">#include </span><span style="color: #000000">"</span><span style="color: #000000">..\..\..\..\..\Candidate\GUI\GUI\Reflection\GuiTypeDescriptor.cpp</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">27</span> <span style="color: #000000"></span><span style="color: #008000">//</span><span style="color: #008000">---------------------------------------------------------------</span><span style="color: #008000"><br /></span><span style="color: #008080">28</span> <span style="color: #008000"></span><span style="color: #000000">#include </span><span style="color: #000000">"</span><span style="color: #000000">..\..\..\..\..\Library\Basic.cpp</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">29</span> <span style="color: #000000">#include </span><span style="color: #000000">"</span><span style="color: #000000">..\..\..\..\..\Library\Exception.cpp</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">30</span> <span style="color: #000000">#include </span><span style="color: #000000">"</span><span style="color: #000000">..\..\..\..\..\Library\String.cpp</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">31</span> <span style="color: #000000">#include </span><span style="color: #000000">"</span><span style="color: #000000">..\..\..\..\..\Library\Threading.cpp</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">32</span> <span style="color: #000000">#include </span><span style="color: #000000">"</span><span style="color: #000000">..\..\..\..\..\Library\Collections\Operation.cpp</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">33</span> <span style="color: #000000"></span><span style="color: #008000">//</span><span style="color: #008000">---------------------------------------------------------------</span><span style="color: #008000"><br /></span><span style="color: #008080">34</span> <span style="color: #008000"></span><span style="color: #000000">#include </span><span style="color: #000000"><</span><span style="color: #000000">Windows.h</span><span style="color: #000000">></span><span style="color: #000000"><br /></span><span style="color: #008080">35</span> <span style="color: #000000"><br /></span><span style="color: #008080">36</span> <span style="color: #000000"></span><span style="color: #0000ff">int</span><span style="color: #000000"> CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, </span><span style="color: #0000ff">int</span><span style="color: #000000"> CmdShow)<br /></span><span style="color: #008080">37</span> <span style="color: #000000">{<br /></span><span style="color: #008080">38</span> <span style="color: #000000">    </span><span style="color: #0000ff">return</span><span style="color: #000000"> </span><span style="color: #000000">0</span><span style="color: #000000">;<br /></span><span style="color: #008080">39</span> <span style="color: #000000">}</span></div></div><br />    啊哈哈哈哈(拖走<br /><br />    VisualStudio的功能是强大的。只要善于用,或者配合MSBuildQ所起到的威力将毫不亚于某些著名工具链。而且VisualStudio~译器生的文gQ基本上VisualStudio都有提供API供你阅读Q所以也可以做很多事情,譬如我这文章说的这P充当了一个编译器的扩展,而且完美集成?img src ="http://www.shnenglu.com/vczh/aggbug/164167.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/vczh/" target="_blank">陈梓?vczh)</a> 2012-01-14 14:09 <a href="http://www.shnenglu.com/vczh/archive/2012/01/14/164167.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++实用技巧(四)http://www.shnenglu.com/vczh/archive/2010/06/27/118829.html陈梓?vczh)陈梓?vczh)Sun, 27 Jun 2010 12:19:00 GMThttp://www.shnenglu.com/vczh/archive/2010/06/27/118829.htmlhttp://www.shnenglu.com/vczh/comments/118829.htmlhttp://www.shnenglu.com/vczh/archive/2010/06/27/118829.html#Feedback16http://www.shnenglu.com/vczh/comments/commentRss/118829.htmlhttp://www.shnenglu.com/vczh/services/trackbacks/118829.htmlVczh Library++3.0被我搞得很离谱。ؓ(f)了开发维护的遍历、减粗心犯下的错误以及(qing)增强单元试、回归测试和试工具Q因此记录下一些开发上的小技巧,以便抛砖引玉Q造福他h。欢q高手来P菜鸟膜拜?br>
    之前的文?/a>讲了指针和内存的一些问题,今天说一下单元测试的问题。如果在团队里面没有对单元测试的框架有要求的话,其实我们可以使用一个最单的Ҏ(gu)来搭建在IDE里面q行的单元测试框Ӟ整个框架只需十几行代码。我们先来考虑一下功能最的单元试框架需要完成什么样的内宏V首先我们要q行一个一个的试用例Q其ơ在一个测试用例里面我们要查一些条件是否成立。D个例子,我们写一个函数将两个字符串连接v来,一般来说要q行下面的测试:(x)
 1 #include "MyUnitTestFramework.h"//{一下我们会(x)展示一下如何用最的代码完成q个头文件的内容
 2 #include ""
 3 
 4 TEST_CASE(StringConcat)
 5 {
 6   TEST_ASSERT(concat("a""b")=="ab");
 7   TEST_ASSERT(concat("a""")=="a");
 8   TEST_ASSERT(concat("""b")=="b");
 9   TEST_ASSERT(concat("""")=="");
10   .
11 }
12 
13 int wmain()
14 {
15   return 0;
16 }

    如果我们的单元测试框架可以这么写Q那昄做v什么事情来都会(x)方便很多Q而且不需要向一些其他的试框架一h册一大堆东西Q或者是写一大堆配置函数。当然这ơ我们只做功能最的试框架Q这个框枉了运行测试以外,不会(x)有其他功能,譬如选择哪些试可以q行啦,q是在出错的时候log一些什么啦之类。之所以要在IDE里面q行Q是因ؓ(f)我们如果做到TEST_ASSERT中出现false的话Q立d该行崩溃Q那么IDE׃(x)帮你定位到出错的TEST_ASSERT中去Q然后给你显C所有的上下文信息,譬如说callstack啦什么的。友好的工具不用直对不v自己啊,q吗非得把单元测试做得那么复杂捏Q凡是单元测试,L要全部运行通过才能提交代码的?br>
    那么我们来看看上面的单元试的代码。首先写了TEST_CASE的那个地方,大括号里面的代码?x)自动运行。其ơTEST_ASSERT?x)在表达式是false的时候崩溃。先从简单的入手吧。如何制造崩溃呢Q最单的办法是抛异常:(x)
1 #define TEST_ASSERT(e) do(if(!(e))throw "今晚没饭吃?;}while(0)

    q里面有两个要注意的地方。首先e要加上小括号Q不然取反操作符有可能做出错误的行为。譬如说当e是a+b==c的时候,加了括号就变成if(!(a+b==c))...Q没有加括号就变成if(!a+b==c)...Q意思就完全变了。第二个L的地Ҏ(gu)我用do{...}while(0)把语句包围v来了。这样做的好处是可以在Q何时候TEST_ASSERT(e)都像一个语句。譬如我们可能这么写Q?br>
1 if(a)
2   TEST_ASSERT(x1);
3 else if(b)
4 {
5   TEST_ASSERT(x2);
6   TEST_ASSERT(x3);
7 }

    如果没有do{...}while(0)包围hQ这个else׃(x)被绑定到宏里面的那个ifQ你的代码就被偷h掉了?br>
    那么现在剩下TEST_CASE(x){y}了。什么东西可以在main函数外面自动q行呢?q个我想熟?zhn)C++的h都会(x)知道Q就是全局变量的构造函数啦。所以TEST_CASE(x){y}那个大括号里面的y只能在全局变量的构造函数里面调用。但是我们知道写一个类的时候,构造函数的大括号写完了Q后面还有类的大括号Q全局变量的名Uͼ和最l的一个分受ؓ(f)了把q些LQ那么显然{y}应该属于一个普通的函数。那么全局变量如何能够使用q个函数呢?Ҏ(gu)很简单,把函数前|声明一下就行了Q?br>
 1 #define TEST_CASE(NAME)                                            \
 2         extern void TESTCASE_##NAME();                             \
 3         namespace vl_unittest_executors                            \
 4         {                                                          \
 5             class TESTCASE_RUNNER_##NAME                           \
 6             {                                                      \
 7             public:                                                \
 8                 TESTCASE_RUNNER_##NAME()                           \
 9                 {                                                  \
10                     TESTCASE_##NAME();                             \
11                 }                                                  \
12             } TESTCASE_RUNNER_##NAME##_INSTANCE;                   \
13         }                                                          \
14         void TESTCASE_##NAME()

    那我们来看看TEST_CASE(x){y}I竟?x)被译成什么代码:(x)
 1 extern void TESTCASE_x();
 2 namespace vl_unittest_executors
 3 {
 4     class TESTCASE_RUNNER_x
 5     {
 6     public:
 7         TESTCASE_RUNNER_x()
 8         {
 9             TESTCASE_x();
10         }
11     } TESTCASE_RUNNER_x_INSTANCE;
12 }
13 void TESTCASE_x(){y}

    Cq里是不是很清楚了捏Q首先在main函数q行之前TESTCASE_RUNNER_x_INSTANCE变量?x)初始化Q然后调用TESTCASE_RUNNER_x的构造函敎ͼ最后运行函数TESTCASE_xQ该函数的内Ҏ(gu)然就是{y}了。这里还能学到宏是如何连接两个名字成Z个名字,和如何写多行的宏的?br>
    于是MyUnittestFramework.h包含这两个宏,其他啥都没有Q是不是很方便呢Q打开Visual C++Q徏立一个工E,引用q个头文Ӟ然后写你的单元测试,最后F5p行了Q多方便啊,啊哈哈哈?br>
    q里需要注意一点,那些单元试的顺序是不受C证的Q特别是你用了多个cpp文g的情况下。于是你在用这个测试框架的同时Q会(x)被迫保证执行一ơ单元测试不?x)对你的全局状态带来什么副作用Q以便两个测试用例交换顺序执行的时候仍然能E_C生相同的l果。这对你写单元测试有帮助Q而且Z让你的代码能够被q么试Q你的代码也?x)写的有条理Q不?x)依赖全局状态,真是一举两得也。而且说不定单元测试用例比你的全局变量的初始化q先执行呢,因此Z使用q个试框架Q你会(x)不得不把你的全局变量隐藏在一个cpp里面Q而暴露出随时可以被调用的一l函数出来。这样也可以让你的代码在使用全局状态的时候更加安全?br>
    今天p到这里了。下一要写什么我q没惛_Q到时候再说吧?

陈梓?vczh) 2010-06-27 20:19 发表评论
]]>
C++实用技巧(三)http://www.shnenglu.com/vczh/archive/2010/06/24/118635.html陈梓?vczh)陈梓?vczh)Thu, 24 Jun 2010 07:03:00 GMThttp://www.shnenglu.com/vczh/archive/2010/06/24/118635.htmlhttp://www.shnenglu.com/vczh/comments/118635.htmlhttp://www.shnenglu.com/vczh/archive/2010/06/24/118635.html#Feedback14http://www.shnenglu.com/vczh/comments/commentRss/118635.htmlhttp://www.shnenglu.com/vczh/services/trackbacks/118635.html    复杂的东西写多了Q如今写点简单的好了。由于功能上的需要,Vczh Library++3.0被我搞得很离谱。ؓ(f)了开发维护的遍历、减粗心犯下的错误以及(qing)增强单元试、回归测试和试工具Q因此记录下一些开发上的小技巧,以便抛砖引玉Q造福他h。欢q高手来P菜鸟膜拜?br>
    今天是关于内存的最后一了?a style="TEXT-DECORATION: underline" href="http://www.shnenglu.com/vczh/archive/2010/06/24/118603.html" target=_blank>上一文?/a>讲了Z么不能对一个东襉K便memset。里面的demo代码Z点小bugQ不q我不喜Ƣ在发文章的时候里面的demo代码也拿ȝ译和q行Q所以大家有什么发现的问题p论吧。这样也便于后来的h不会(x)受到误导。这ơ说的仍然是构造函数和析构函数的事情,不过我们通过亲手开发一个智能指针的Ҏ(gu)Q知道引用计数如何帮助管理资源,以及(qing)错误使用引用计数的情c(din)?br>
    首先先来看一下智能指针是如何帮助我们理内存的。现在智能指针的实现非常多,我就假设q个cd叫Ptr<T>吧。这跟Vczh Library++ 3.0所使用的实C栗?/p>
 1 class Base
 2 {
 3 public:
 4   virtual ~Base(){}
 5 };
 6 
 7 class Derived1 : public Base
 8 {
 9 };
10 
11 class Derived2 : public Base
12 {
13 };
14 
15 //---------------------------------------
16 
17 List<Ptr<Base>> objects;
18 objects.Add(new Derived1);
19 objects.Add(new Derived2);
20 
21 List<Ptr<Base>> objects2;
22 objects2.Add(objects[0]);

    当然q里的List也是Vczh Library++3.0实现的,不过q玩意儿跟vector也好跟C#的List也好都是一个概念,因此也就不需要多加解释了。我们可以看到智能指针的一个好处,只要没有循环引用出现Q你无论怎么复制它,最lL可以被析构掉的。另一个例子告诉我们智能指针如何处理类型{换:(x)
1 Ptr<Derived1> d1=new Derived1;
2 Ptr<Base> b=d1;
3 Ptr<Derived2> d2=b.Cast<Derived2>();
4 // d2是空Q因为b指向的是Derived1而不是Derived2?/span>

    q就如同我们Derived1*可以隐式转换到Base*Q而当你用dynamic_cast<Derived2*>(static_cast<Base*>(new Derived1))?x)得?一栗智能指针在帮助我们析构对象的同Ӟ也要做好cd转换的工作?br>
    好了Q现在先让我们一步一步做出那个Ptr<T>。我们需要清楚这个智能指针所要实现的功能是什么,然后我们一个一个来做。首先让我们列出一张表Q?br>    1、没有参数构造的时候,初始化ؓ(f)I?br>    2、用指针构造的时候,拥有那个指针Qƈ且在没有M指针指向那个指针的时候删除掉该指针?br>    3、智能指针进行复制的时候,两个指针共同拥有该内部指针?br>    4、智能指针可以用新的智能指针或裸指针重新赋倹{?br>    5、需要支持隐式指针类型{换,static_cast不支持而dynamic_cast支持的{换则使用Cast<T2>()成员函数来解冟?br>    6、如果一个裸指针直接用来创徏两个指针的话Q期望的情况是当两个指针析构掉的时候,该指针会(x)被delete两次从而崩溃?br>    7、不处理循环引用?br>
    最后两点实际上是错误用智能指针的最常见的两U情c(din)我们从1?一个一个实现。首先是1。智能指针可以隐式{换成boolQ可以通过operator->()拿到内部的T*。在没有使用参数构造的时候,需要{换成falseQ以?qing)拿?Q?br>
 1 template<typename T>
 2 class Ptr
 3 {
 4 private:
 5   T* pointer;
 6   int* counter;
 7 
 8   void Increase()
 9   {
10     if(counter)++*counter;
11   }
12 
13   void Decrease()
14   {
15     if(counter && --*counter==0)
16     {
17       delete counter;
18       delete pointer;
19       counter=0;
20       pointer=0;
21     }
22   }
23 
24 public:
25   Ptr():pointer(0),counter(0)
26   {
27   }
28 
29   ~Ptr()
30   {
31     Decrease();
32   }
33 
34   operator bool()const
35   {
36     return counter!=0;
37   }
38 
39   T* operator->()const
40   {
41     return pointer;
42   }
43 };

    在这里我们实C构造函数和析构函数。构造函数把内部指针和引用计数的指针都初始化为空Q而析构函数则q行引用计数的减一操作。另外两个操作符重蝲很容易理解。我们主要来看看Increase函数和Decrease函数都分别做了什么。Increase函数在引用计数存在的情况下,把引用计数加一。而Decrease函数在引用计数存在的情况下,把引用计数减一Q如果引用计数在减一q程中变成了0Q则删掉拥有的资源?br>
    当然Cq个时候智能指针还不能用,我们必须替他加上复制构造函敎ͼoperator=操作W重载以?qing)用指针赋值的情况。首先让我们来看使用指针赋值的话我们应该加上什么:(x)
 1   Ptr(T* p):pointer(0),counter(0)
 2   {
 3     *this=p;
 4   }
 5 
 6   Ptr<T>& operator=(T* p)
 7   {
 8     Decrease();
 9     if(p)
10     {
11       pointer=p;
12       counter=new int(1);
13     }
14     else
15     {
16       pointer=0;
17       counter=0;
18     }
19     return *this;
20   }

    q里q是偷工减料了的Q构造函数接受了指针的话Q还是{loperator=去调用了。当一个智能指针被一个新指针赋值的时候,我们首先要减掉一个引用计敎ͼ因ؓ(f)原来的指针再也不被这个智能指针共享了。之后就q行判断Q如果来的是0Q那么就变成I。如果不?Q就拥有该指针,引用计数初始化成1。于是我们就可以q么使用了:(x)
1 Ptr<Base> b=new Derived1;
2 Ptr<Derived2> d2=new Derived2;

    让我们开始复制他们吧。复制的要领是,先把之前拥有的指针脱LQ然后连接到一个新的智能指针上面去。我们知道非I智能指针有多少个,ȝ引用计数的和是多少Q只是分配到各个指针上面的数字不一栯已Q?br>
 1   Ptr(const Ptr<T>& p):pointer(p.pointer),counter(p.counter)
 2   {
 3     Increase();
 4   }
 5 
 6   Ptr<T>& operator=(const Ptr<T>& p)
 7   {
 8     if(this!=&p)
 9     {
10       Decrease();
11       pointer=p.pointer;
12       counter=p.counter;
13       Increase();
14     }
15     return *this;
16   }

    在上一文章有朋友指出重蝲operator=的时候需要考虑是不是自p值给自己Q其实这是很正确的。我们写每一cȝ时候,特别是当cL有自己控制的资源的时候,需要非常注意这件事情。当然如果只是复制几个对象而不?x)new啊deleteq是close什么handleQ那查不查也无所谓了。在q里我们非常清楚Q当增加一个新的非I智能指针的时候,引用计数的d?x)加一。当修改一个非I智能指针的l果也是非空的时候,引用计数的和保持不变。当然这是应该的Q因为我们需要在所有非I智能指针都被毁掉的时候,释放受保护的所有资源?br>
    Cq里一个智能指针基本上已经能用了,但是q不能处理父cdcȝ情况。这个是比较ȝ的,一个Ptr<Derived>事实上没有权限访问Ptr<Base>的内部对象。因此我们需要通过友元cL解决q个问题。现在让我们来添加两个新的函数吧Q从一个Q意的Ptr<C>复制到Ptr<T>Q然后保证只有当C*可以隐式转换成T*的时候编译能够通过Q?br>
 1   template<X> friend class Ptr;
 2 
 3   template<typename C>
 4   Ptr(const Ptr<C>& p):pointer(p.pointer),counter(p.counter)
 5   {
 6     Increase();
 7   }
 8 
 9   template<typename C>
10   Ptr<T>& operator=(const Ptr<C>& p)
11   {
12     Decrease();
13     pointer=p.pointer;
14     counter=p.counter;
15     Increase();
16     return *this;
17   }

    注意q里我们的operator=q不用检查是不是自己l自p|因ؓ(f)q是两个不同的类Q相同的话会(x)调用上面那个operator=的。如果C*不能隐式转换到T*的话Q这里的pointer=p.pointer׃(x)p|Q从而满了我们的要求?br>
    现在我们能够做的事情更多了Q?br>
1 Ptr<Derived1> d1=new Derived1;
2 Ptr<Base> b=d1;

    于是我们只剩下最后一个Cast函数了。这个函数内部用dynamic_cast来做判断Q如果{换失败,?x)返回空指针Q?br>
 1   tempalte<typename C>
 2   Ptr<C> Cast()const
 3   {
 4     C* converted=dynamic_cast<C*>(pointer);
 5     Ptr<C> result;
 6     if(converted)
 7     {
 8       result.pointer=converted;
 9       result.counter=counter;
10       Increase();
11     }
12     return result;
13   }

    q是一Uhack的方法,qx是不鼓励?#8230;…不过因ؓ(f)操作的都是PtrQ而且特化Ptr也是使用错误的一U,所以这里就不管了。我们会(x)查dynamic_cast的结果,如果成功了,那么?x)返回一个非I的新智能指针,而且q个时候我们也要记住Increase一下?br>
    好了Q基本功能就完成了。当然一个智能指针还要很多其他功能,譬如说比较什么的Q这个就你们自己搞定哈?br>
    指针和内存就说到q里了,下一讲如何利用一个好的IDE构造轻量单元试pȝ。我们都说好的工兯够提高生产力Q因此这U方法不能脱M个好的IDE使用?

陈梓?vczh) 2010-06-24 15:03 发表评论
]]>
C++实用技巧(二)http://www.shnenglu.com/vczh/archive/2010/06/24/118603.html陈梓?vczh)陈梓?vczh)Wed, 23 Jun 2010 18:12:00 GMThttp://www.shnenglu.com/vczh/archive/2010/06/24/118603.htmlhttp://www.shnenglu.com/vczh/comments/118603.htmlhttp://www.shnenglu.com/vczh/archive/2010/06/24/118603.html#Feedback23http://www.shnenglu.com/vczh/comments/commentRss/118603.htmlhttp://www.shnenglu.com/vczh/services/trackbacks/118603.htmlVczh Library++3.0被我搞得很离谱。ؓ(f)了开发维护的遍历、减粗心犯下的错误以及(qing)增强单元试、回归测试和试工具Q因此记录下一些开发上的小技巧,以便抛砖引玉Q造福他h。欢q高手来P菜鸟膜拜?br>
    上一文?/a>讲到了如何检查内存泄霌Ӏ其实只要肯用C++的STL里面的高U功能的话,内存泄露是很Ҏ(gu)避免的。我在开发Vczh Library++ 3.0的时候,所有的试用例都保证跑完了没有内存泄露。但是很可惜有些C++团队不能使用异常Q更甚者不允许写构造函数析构函Cc,前一个还好,后一个简直就是在用C。当然有q些变态规定的地方STL都是用不了的Q所以我们更加需要扎实的基础来开发C++E序?br>
    今天q一主要还是讲指针的问题。因Z一文章一W带q,今天来详细讲内存泄漏或者野指针发生的各U情c(din)当然我不可能一下子丑և全部的例子,只能说一些常见的?br>
    一、错误覆盖内存?br>
    之前提到的不能随便ؕmemset其实是Z避免q个问题的。其实memcpy也不能ؕ用,我们来看一个例子,最单的Q?br>
 1 #define MAX_STRING 20;
 2 
 3 struct Student
 4 {
 5   char name[MAX_STRING];
 6   char id[MAX_STRING];
 7   int chinese;
 8   int math;
 9   int english;
10 };

    大家对这U结构肯定十分熟(zhn),毕竟是大学时候经常要写的作业?#8230;…好了Q大家很Ҏ(gu)看得出来q其实是C语言的经典写法。我们拿到手之后Q一般会(x)先初始化一下,然后赋倹{?br>
1 Student vczh;
2 memset(&vczh, 0sizeof(vczh));
3 strcpy(vczh.name, "vczh");
4 strcpy(vczh.id, "VCZH'S ID");
5 vczh.chinese=70;
6 vczh.math=90;
7 vczh.english=80;

    Z么要在这里用memset呢?memset的用处是一D内存的每一个字节都讄成同一个数字。这里是0Q因此两个字W串成员的所有字节都?x)变?。因此在memset了Student之后Q我们通过正常Ҏ(gu)来访问name和id的时候都?x)得到空丌Ӏ而且如果Student里面有指针的话,0指针代表的是没有指向M有效对象Q因此这个时候对指针指向的对象进行读写就?x)立d溃。对于其他数|0一般作为初始g不会(x)有什么问题(double什么的要小心)。这是我们写程序的时候用memset的原因?br>
    好了Q如今社?x)进步,人民当家做主了,ȝ们再也不需要受到可恶的C语言剥削了,我们可以使用C++Q因此我们借助STL的力量把Student改写成下面这U带有C++味道的Ş式:(x)
1 struct Student
2 {
3   std::string name;
4   std::string id;
5   int chinese;
6   int math;
7   int english;
8 };

    我们仍然需要对Studentq行初始化,不然三个分数q是随机倹{但是我们又不想每一ơ创建的时候都对他们分别进行赋值初始化?。这个时候你心里可能q是想着memsetQ?span style="COLOR: red">q就错了Q在memset的时候,你会(x)把std::string内部的不知道什么东西也lmemset掉。假如一个空的std::string里面存放的指针指向的是一个空的字W串而不是用0来代表空的时候,一下子内部的指针就被你h0Q等下std::string的析构函数就没办法delete掉指针了Q于?span style="COLOR: red">内存泄露出C。有些朋友可能不知道上面那句话说的是什么意思,我们现在来模拟一下不能memset的std::string要怎么实现?br>
    Z让memset一定出现内存泄Ԍ那么std::string里面的指针必Lq都指向一个有效的东西。当然我们还需要在字符串进行复制的时候复制指针。我们这里不考虑各种优化技术,用最单的Ҏ(gu)做一个字W串出来Q?br>
 1 class String
 2 {
 3 private:
 4   char* buffer;
 5 
 6 public:
 7   String()
 8   {
 9     buffer=new char[1];
10     buffer[0]=0;
11   }
12 
13   String(const char* s)
14   {
15     buffer=new char[strlen(s)+1];
16     strcpy(buffer, s);
17   }
18 
19   String(const String& s)
20   {
21     buffer=new char[strlen(s.buffer)+1];
22     strcpy(buffer, s.buffer);
23   }
24 
25   ~String()
26   {
27     delete[] buffer;
28   }
29 
30   String& operator=(const String& s)
31   {
32     delete[] buffer;
33     buffer=new char[strlen(s.buffer)+1];
34     strcpy(buffer, s.buffer);
35   }
36 };

    于是我们来做一下memset。首先定义一个字W串变量Q其ơmemset掉,让我们看看会(x)发生什么事情:(x)
1 string s;
2 memset(&s, 0sizeof(s));

    W一行我们构造了一个字W串s。这个时候字W串的构造函数就?x)开始运行,因此strcmp(s.buffer, "")==0。第二行我们把那个字W串lmemset掉了。这个时候s.buffer==0。于是函数结束了Q字W串的析构函数尝试deleteq个指针。我们知道delete一?是不?x)有问题的,因此E序不会(x)发生错误?span style="COLOR: red">我们zȝ生把构造函数赋值给buffer的new char[1]l丢?/strong>Q铁定发生内存泄Ԍ

    好了Q提出问题总要解决问题Q我们不使用memset的话Q怎么初始化Student呢?q个十分好做Q我们只需要ؓ(f)Student加上构造函数即可:(x)
1 struct Student
2 {
3   .//不重复那些声?/span>
4 
5   Student():chinese(0),math(0),english(0)
6   {
7   }
8 };

    q样容易多了。每当我们定义一个Student变量的时候,所有的成员都初始化好了。name和id因ؓ(f)string的构造函C自己初始化了Q因此所有的成员也都初始化了。加入Student用了一半我们想再初始化一下怎么办呢Q也很容易:(x)
1 Student vczh;
2 .//各种使用
3 vczh=Student();

    l过一个等h作符的调用,旧Student的所有成员就被一个新的初始化q的Studentl覆盖了Q就如同我们对一个int变量重新赋g样常见。当然因为各U复制经怼(x)出现Q因此我们也要跟上面贴出来的string的例子一P实现好那4个函数。至此我十分不理解ؓ(f)什么某些团队不允许使用构造函敎ͼ我猜是Z可以memsetQ其实是很没道理的?br>
    二、异常?/strong>

    咋一看内存泄露跟异常好像没什么关p,但实际上q种情况更容易发生。我们来看一个例子:(x)
 1 char* strA=new char[MAX_PATH];
 2 if(GetXXX(strA, MAX_PATH)==ERROR) goto RELEASE_STRA;
 3 char* strB=new char[MAX_PATH];
 4 if(GetXXX(strB, MAX_PATH)==ERROR) goto RELEASE_STRB;
 5 
 6 DoSomething(strA, strB);
 7 
 8 RELEASE_STRB:
 9 delete[] strB;
10 RELEASE_STRA:
11 delete[] strA;

    怿q肯定是大家的常用模式。我在这里也不是教唆大家使用gotoQ不q对于这U例子来_(d)用goto是最优美的解军_法了。但是大家可以看出来Q我们用的是C++Q因里有new。如果DoSomething发生了异常怎么办呢Q如果GetXXX发生了异常怎么办呢Q我们这里没有Q何的try-catchQ一有异常,函数里克l束Q两行可怜的delete׃?x)被执行CQ?span style="COLOR: red">于是内存泄漏发生?/strong>Q?br>
    那我们如何避免这U情况下的内存泄露呢Q一些可q盆友可能会(x)惛_Q既然是因ؓ(f)没有catch异常才发生的内存泄露Q那我们来catch吧:(x)
 1 char* strA=new char[MAX_PATH];
 2 try
 3 {
 4   if(GetXXX(strA, MAX_PATH)==ERROR) goto RELEASE_STRA;
 5   char* strB=new char[MAX_PATH];
 6   try
 7   {
 8     if(GetXXX(strB, MAX_PATH)==ERROR) goto RELEASE_STRB;
 9     DoSomething(strA, strB);
10   }
11   catch()
12   {
13     delete[] strB;
14     throw;
15   }
16 }
17 catch()
18 {
19   delete[] strA;
20   throw;
21 }
22 
23 RELEASE_STRB:
24 delete[] strB;
25 RELEASE_STRA:
26 delete[] strA;

    你能接受吗?当然是不能的。问题出在哪里呢Q因为C++没有try-finally。你看这些代码到处都是雷同的东西Q显然我们需要编译器帮我们把q些问题搞定。最好的解决Ҏ(gu)是什么呢Q显然还是构造函数和析构函数。MCQ?span style="COLOR: red">如果惌事情成对发生Q那么用构造函数和析构函数?br>
    W一步,GetXXX昄只能支持C模式的东西,因此我们要写一个支持C++的:(x)
 1 bool GetXXX2(string& s)
 2 {
 3   char* str=new char[MAX_PATH];
 4   bool result;
 5   try
 6   {
 7     result=GetXXX(str, MAX_PATH);
 8     if(result)s=str;
 9   }
10   catch()
11   {
12     delete[] str;
13     throw;
14   }
15   delete[] str;
16   return result;
17 }

    借助q个函数我们可以看到Q因为有了GetXXXq种C的东西,D我们多了多少ȝ。不q这L一x逸的Q有了GetXXX2和修改之后的DoSomething2之后Q我们就可以用更单的Ҏ(gu)来做了:(x)
1 string a,b;
2 if(GetXXX2(a) && GetXXX2(b))
3 {
4   DoSomething2(a, b);
5 }

    多么单易懂。这个代码在M地方发生了异常,所有new的东襉K?x)被delete。这是析构函数的一个好处。一个变量的析构函数在这个变量超Z作用域的时候一定会(x)被调用,无论代码是怎么走出ȝ?br>
    今天p到这里了。说了这么多q是惌大家不要看构造函数和析构函数。那U微不道的因ؓ(f)一部分不是瓶颈的性能问题而放弃构造函数和析构函数的做法,l究是要Z修bug而加班的。只要明白ƈ用好了构造函数、析构函数和异常Q那么C++的特性也可以跟C一h楚明白便于理解,而且写出来的代码更好看的。大家期待第三篇哈?

陈梓?vczh) 2010-06-24 02:12 发表评论
]]>
C++实用技巧(一Q?/title><link>http://www.shnenglu.com/vczh/archive/2010/06/22/118493.html</link><dc:creator>陈梓?vczh)</dc:creator><author>陈梓?vczh)</author><pubDate>Tue, 22 Jun 2010 13:16:00 GMT</pubDate><guid>http://www.shnenglu.com/vczh/archive/2010/06/22/118493.html</guid><wfw:comment>http://www.shnenglu.com/vczh/comments/118493.html</wfw:comment><comments>http://www.shnenglu.com/vczh/archive/2010/06/22/118493.html#Feedback</comments><slash:comments>29</slash:comments><wfw:commentRss>http://www.shnenglu.com/vczh/comments/commentRss/118493.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/vczh/services/trackbacks/118493.html</trackback:ping><description><![CDATA[    复杂的东西写多了Q如今写点简单的好了。由于功能上的需要,<a style="TEXT-DECORATION: underline" target=_blank>Vczh Library++3.0</a>被我搞得很离谱。ؓ(f)了开发维护的遍历、减粗心犯下的错误以及(qing)增强单元试、回归测试和试工具Q因此记录下一些开发上的小技巧,以便抛砖引玉Q造福他h。欢q高手来P菜鸟膜拜?br><br>    C++实谓各种语言中的软肋Q功能强大,陷阱更强大。当然我认ؓ(f)一门语a用得不好完全是程序员的责任,不过因ؓ(f)C++涉及(qing)到的概念实在是太多,想用好实在也不是一件容易的事情。C++开发的时候L?x)遇到各U各L(fng)问题Q其中最严重的无非是内存相关的。C语言׃l构单,内存处理h虽然不得力,但ȝ来说惯用法已l深入h心,因此也不?x)造成什么很隑֏现的错误。C++׃一样了。有了虚函数、构造函数、析构函数、复制构造函数和operator=重蝲之后Q还是有很多人喜Ƣ把一个类直接写进文g,或者拿来memsetQ代码一团ؕ麻,不知(zhn)改也。但是不能因此因噎废食,像某h因ؓ(f)C++带来的心智问题太多,自己搞不定,自己团队也搞不定Q就说C++不好一栗?br><br>    因此W一文章主要针对内存来讌Ӏ我们处理内存,W一件事是不要有内存泄霌Ӏ内存泄露不能等到测试的时候,通过长时间运行程序ƈ观察d理器的Ҏ(gu)来做Q这昄已经晚了。幸好Visual C++l了我们一个十分好用的工具Q_CrtDumpMemoryLeaks函数。这个函C(x)在Debug模式下往Visual Studio的outputH口打印出那个时候你newQmallocQ了但是q没deleteQfreeQ的所有内存块的地址、长度、前N个字节的内容和其他信息。怎么做呢Q其实很单:(x)<br> <div style="BORDER-BOTTOM: #cccccc 1px solid; BORDER-LEFT: #cccccc 1px solid; PADDING-BOTTOM: 4px; BACKGROUND-COLOR: #eeeeee; PADDING-LEFT: 4px; WIDTH: 98%; PADDING-RIGHT: 5px; FONT-SIZE: 13px; WORD-BREAK: break-all; BORDER-TOP: #cccccc 1px solid; BORDER-RIGHT: #cccccc 1px solid; PADDING-TOP: 4px"><span style="COLOR: #008080"> 1</span> <span style="COLOR: #0000ff">#define</span><span style="COLOR: #000000"> _CRTDBG_MAP_ALLOC</span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080"> 2</span> <span style="COLOR: #000000">#include </span><span style="COLOR: #000000"><</span><span style="COLOR: #000000">stdlib.h</span><span style="COLOR: #000000">></span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080"> 3</span> <span style="COLOR: #000000">#include </span><span style="COLOR: #000000"><</span><span style="COLOR: #000000">crtdbg.h</span><span style="COLOR: #000000">></span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080"> 4</span> <span style="COLOR: #000000">#include </span><span style="COLOR: #000000"><</span><span style="COLOR: #000000">windows.h</span><span style="COLOR: #000000">></span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080"> 5</span> <span style="COLOR: #000000"><br></span><span style="COLOR: #008080"> 6</span> <span style="COLOR: #000000"></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000"> wmain(vint argc , wchar_t</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000"> args[])<br></span><span style="COLOR: #008080"> 7</span> <span style="COLOR: #000000">{<br></span><span style="COLOR: #008080"> 8</span> <span style="COLOR: #000000">    </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> q里q行E序Qƈ在下面的函数调用之前delete掉所有new的东?/span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080"> 9</span> <span style="COLOR: #008000"></span><span style="COLOR: #000000">    _CrtDumpMemoryLeaks();<br></span><span style="COLOR: #008080">10</span> <span style="COLOR: #000000">    </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br></span><span style="COLOR: #008080">11</span> <span style="COLOR: #000000">}</span></div> <br>    我们只需要在注释的地方完成我们程序的功能Q然后确信自己已ldelete掉所有应该delete的东西,最后_CrtDumpMemoryLeaks()函数调用的时候就可以打印出没被delete的东西了。这个方法十分神奇,因ؓ(f)你只需要在main函数所在的cpp文gq么#include一下,所有的cpp文g里面的new都会(x)受到监视Q跟q_所用的用宏把newl换掉的q种破方法截然不同。如果你使用了全局变量的话也要心Q因为全局变量的析构函数是在main函数l束之后才执行的Q因此如果在全局变量的析构函数里面delete的东西仍然会(x)被_CrtDumpMemoryLeaks函数当成泄露掉的资源对待。当然本为全局变量可以用,但是全局变量的赋值必dmain里面做,释放也是Q除非那个全局变量的构造函数没有申请Q何内存,所以这也是一个很好的查方法?br><br>    不过上面也仅仅是一个告诉你有没有内存泄漏的Ҏ(gu)|了。那么如何避免内存泄露呢Q当然在设计一些性能要求没有比操作系l更加严格的E序的时候,可以使用以下Ҏ(gu)Q?br>    1、如果构造函数new了一个对?span style="COLOR: red"><strong>q用成员指针变?/strong></span>保存的话Q那么必d析构函数delete它,q且不能有ؓ(f)了某些便利而将q个对象的所有权转让出去的事情发生?br>    2、在能用shared_ptr的时候,量使用shared_ptr。shared_ptr只要你不发生循环引用Q那么这个东西可以安全地互相传递、随便你攑֜什么容器里面添加删除、你x哪里放在哪里,再也不用考虑q个对象的生命周期问题了?br>    3、不要在有构造函数和析构函数的对象上使用memsetQ或者memcpyQ。如果一个对象需要memsetQ那么在该对象的构造函数里面memset自己。如果你需要memset一个对象数l,那也在该对象的构造函数里面memset自己?span style="COLOR: red"><strong>如果你需要memset一个没有构造函数的复杂对象Q那么请Zd一个构造函敎ͼ除非那是别h的API提供的东?/strong></span>?br>    4、如果一个对象是l承了其他东西,或者某些成员被标记了virtual的话Q绝对不要memset。对象是独立的,也就是说父类内部l构的演变不需要对子类负责。哪天父c里面加了一个string成员Q被子类一memsetQ就Ʋ哭无泪了?br>    5、如果需要ؓ(f)一个对象定义构造函敎ͼ那么q复制构造函数、operator=重蝲和析构函数都全部写全。如果不惛_复制构造函数和operator=的话Q那么用一个空的实现写在private里面Q确保Q何试图调用这些函数的代码都出现编译错误?br>    6、如果你实在很喜ƢC语言的话Q那ȝ换一个只支持C不支持C++的编译器Q全面杜l因用了C++而导致你的C坏掉的情况出现?br><br>    什么是循环引用呢?如果两个对象互相使用一个shared_ptr成员变量直接或者间接指向对方的话,是循环引用了。在q种情况下引用计C(x)失效Q因为就外边的shared_ptr全释攑օ了,引用计数也不?x)?的?br><br>    今天p到这里了Q过几天我高兴的话再写一箋集,如果我持l高兴的话呢……嗯嗯……? <img src ="http://www.shnenglu.com/vczh/aggbug/118493.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/vczh/" target="_blank">陈梓?vczh)</a> 2010-06-22 21:16 <a href="http://www.shnenglu.com/vczh/archive/2010/06/22/118493.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss> <footer> <div class="friendship-link"> <p>лǵվܻԴȤ</p> <a href="http://www.shnenglu.com/" title="精品视频久久久久">精品视频久久久久</a> <div class="friend-links"> </div> </div> </footer> <a href="http://www.bxxlsl.cn" target="_blank">˾þþþƷ</a>| <a href="http://www.wannengsou.cn" target="_blank">޾ƷҹVAþó</a>| <a href="http://www.niugu6.cn" target="_blank">þҹ³˿ƬҹƷ</a>| <a href="http://www.ganzhoupei.cn" target="_blank">һaƬþëƬëƬ</a>| <a href="http://www.yaott2.cn" target="_blank">þһҹ </a>| <a href="http://www.fengbiaochem.com.cn" target="_blank">þþ</a>| <a href="http://www.sh-ar.cn" target="_blank">þù޸ۿ</a>| <a href="http://www.uqtl.cn" target="_blank">ŷսպ91ۺһþþ </a>| <a href="http://www.usgold.cn" target="_blank">þþƷһպ</a>| <a href="http://www.urzf.cn" target="_blank">ɫʹþۺ</a>| <a href="http://www.yweishang.cn" target="_blank">þþþùƷ</a>| <a href="http://www.abcdds.cn" target="_blank">ڸþþþþ</a>| <a href="http://www.jywxhs.cn" target="_blank">þþþӰԺС</a>| <a href="http://www.snaiye.cn" target="_blank">ݺݾƷþþĻ</a>| <a href="http://www.3lr9a.cn" target="_blank">þùƷƵ</a>| <a href="http://www.jfjn.net.cn" target="_blank">ݺ88ۺϾþþþۺ</a>| <a href="http://www.qcbijj.cn" target="_blank">vĻþ 뾫ƷþɪӰ </a>| <a href="http://www.gx263.cn" target="_blank">Ʒ99þþþƷ</a>| <a href="http://www.myth9.cn" target="_blank">Ʒ99þþþ91gav</a>| <a href="http://www.xindouvcd.cn" target="_blank">޾Ʒһþþ</a>| <a href="http://www.zzcjw.cn" target="_blank">þþƷѴƬƬ</a>| <a href="http://www.lzcoxag.cn" target="_blank">1000Ʒþþþþþþ</a>| <a href="http://www.fzbn.net.cn" target="_blank">Ʒþþþþ</a>| <a href="http://www.ter2.cn" target="_blank">þ˳ƷCAOPOREN</a>| <a href="http://www.555yyy.cn" target="_blank">99þþƷһѿ</a>| <a href="http://www.qhd33.cn" target="_blank">þþƷԴվ</a>| <a href="http://www.kangle.net.cn" target="_blank">һƷ˾þ</a>| <a href="http://www.gp9222.cn" target="_blank">þþþavӰ</a>| <a href="http://www.icxun.cn" target="_blank">þþƷѹۿ</a>| <a href="http://www.zjhgkjjt.com.cn" target="_blank">˾þAV</a>| <a href="http://www.sh-bz.com.cn" target="_blank">ɫþþۺƷ</a>| <a href="http://www.nxyb.net.cn" target="_blank">þþþþþþþþþþþ</a>| <a href="http://www.cn1s.cn" target="_blank">ݺɫþþۺ</a>| <a href="http://www.13542350234.cn" target="_blank">ŷ龫Ʒþþþþþþžž</a>| <a href="http://www.wannianl.cn" target="_blank">˾þۺ2020</a>| <a href="http://www.drxt.com.cn" target="_blank">ŷþۺ</a>| <a href="http://www.yingkounews.com.cn" target="_blank">Ʒþһ</a>| <a href="http://www.qq577.cn" target="_blank">þùƷ99Ʒ987</a>| <a href="http://www.qilehu.cn" target="_blank">þþƷ</a>| <a href="http://www.xiezongjun.cn" target="_blank">þrоƷƵ</a>| <a href="http://www.aqcg.cn" target="_blank">Ļ˾Ʒþò</a>| <script> (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })(); </script> </body>