• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            colorful

            zc qq:1337220912

             

            why enable_shared_from_this

             為什么會有 tr1::enable_shared_from_this 這個類,一直不解,直到看了Stephan T. Lavavej給出的關于shared_ptr 的PPT。 Stephan T. Lavavej是Visual C++ Libraries Developer。

            他給的例子是:

            struct Ansible {
                shared_ptr<Ansible> get_shared() {
                    shared_ptr<Ansible> ret(this);
                    return ret;
                }
            };

            int main() {
                shared_ptr<Ansible> a(new Ansible);
                Ansible& r = *a;
                shared_ptr<Ansible> b = r.get_shared();
            }

            Result: DOUBLE DELETION


            然后使用enable_shared_from_this 就對了:

            struct Ansible
                : public enable_shared_from_this<Ansible> { };

            int main() {
                shared_ptr<Ansible> a(new Ansible);
                Ansible& r = *a;
                shared_ptr<Ansible> b = r.shared_from_this();
            }

            a and b share ownership, as if:
            shared_ptr<Ansible> b = a;



            為什么?看看enable_shared_from_this 的實現://也可看boost

            template<class _Ty> class enable_shared_from_this
             { // provide member functions that create shared_ptr to this
            public:
             typedef _Ty _EStype;

             shared_ptr<_Ty> shared_from_this()
              { // return shared_ptr
              return shared_ptr<_Ty>(_Wptr);
              }

             shared_ptr<const _Ty> shared_from_this() const
              { // return shared_ptr
              return shared_ptr<const _Ty>(_Wptr);
              }

            protected:
             enable_shared_from_this()
              { // construct (do nothing)
              }

             enable_shared_from_this(const enable_shared_from_this& _Right)
              : _Wptr(_Right._Wptr)
              { // construct
              }

             enable_shared_from_this& operator=(const enable_shared_from_this& _Right)
              { // assign
              _Wptr = _Right._Wptr;
              return *this;
              }

             ~enable_shared_from_this()
              { // destroy (do nothing)
              }

            private:
             template<class _Ty1,
              class _Ty2>
              friend void _Do_enable(
               _Ty1 *,
               enable_shared_from_this<_Ty2>*,
               _Ref_count_base *);

             mutable weak_ptr<_Ty> _Wptr;
             };


            enable_shared_from_this 的member可是一個weak_ptr.

            當然,從enable_shared_from_this繼承后,遇到shared_ptr后,member _Wptr 是怎樣工作的,另有玄機。 可以設斷點在 _Do_enable 里,有助于理解。

            看似簡單的share_ptr, 被實現的看似危機四伏。

            posted @ 2012-04-07 11:57 多彩人生 閱讀(426) | 評論 (0)編輯 收藏

            mutable關鍵字

            mutalbe的中文意思是“可變的,易變的”,跟constant(既C++中的const)是反義詞。

              在C++中,mutable也是為了突破const的限制而設置的。被mutable修飾的變量,將永遠處于可變的狀態,即使在一個const函數中。

              我們知道,如果類的成員函數不會改變對象的狀態,那么這個成員函數一般會聲明成const的。但是,有些時候,我們需要在const的函數里面修改一些跟類狀態無關的數據成員,那么這個數據成員就應該被mutalbe來修飾。

              下面是一個小例子:

            class ClxTest
            {
             public:
              void Output() const;
            };

            void ClxTest::Output() const
            {
             cout << "Output for test!" << endl;
            }

            void OutputTest(const ClxTest& lx)
            {
             lx.Output();
            }

              類ClxTest的成員函數Output是用來輸出的,不會修改類的狀態,所以被聲明為const的。

              函數OutputTest也是用來輸出的,里面調用了對象lx的Output輸出方法,為了防止在函數中調用其他成員函數修改任何成員變量,所以參數也被const修飾。

               如果現在,我們要增添一個功能:計算每個對象的輸出次數。如果用來計數的變量是普通的變量的話,那么在const成員函數Output里面是不能修改該 變量的值的;而該變量跟對象的狀態無關,所以應該為了修改該變量而去掉Output的const屬性。這個時候,就該我們的mutable出場了——只要 用mutalbe來修飾這個變量,所有問題就迎刃而解了。

              下面是修改過的代碼:

            class ClxTest
            {
             public:
              ClxTest();
              ~ClxTest();

              void Output() const;
              int GetOutputTimes() const;

             private:
              mutable int m_iTimes;
            };

            ClxTest::ClxTest()
            {
             m_iTimes = 0;
            }

            ClxTest::~ClxTest()
            {}

            void ClxTest::Output() const
            {
             cout << "Output for test!" << endl;
             m_iTimes++;
            }

            int ClxTest::GetOutputTimes() const
            {
             return m_iTimes;
            }

            void OutputTest(const ClxTest& lx)
            {
             cout << lx.GetOutputTimes() << endl;
             lx.Output();
             cout << lx.GetOutputTimes() << endl;
            }

              計數器m_iTimes被mutable修飾,那么它就可以突破const的限制,在被const修飾的函數里面也能被修改。

            posted @ 2012-04-05 16:50 多彩人生 閱讀(244) | 評論 (0)編輯 收藏

            using namespace

            // myclass.h
            using namespace std;  // 所有包含myclass.h的文件對std都可見,  所以一般不要將它放在頭文件中,以免污染全局空間
            class myclass
            {
            }

            ///////////////////////////////////////////////////////////

            // myclass.h
            class myclass
            {
                  
            using namespace std;  // 錯, 不能放在類原型中
            }


            ///////////////////////////////////////////////////////////

            // myclass.h
            class myclass
            {
                 
            void foo()
                 {
                     
            using namespace std;   // 正確, std只本函數可見
                     list<int> col;
                 }
            }


            ////////////////////////////////////////////////////////////

            // myclass.h
            class myclass
            {
                  
            void foo();
            }

            // myclass.cpp
            void myclass::foo()
            {
                  
            using namespace std; // 正確, std只本函數可見
            }

            posted @ 2012-04-05 14:33 多彩人生 閱讀(195) | 評論 (0)編輯 收藏

            wxWidgets+boost::asio "socket_types.hpp(22) : fatal error C1189: #error : WinSock.h has already been included"

            http://blog.csdn.net/gzlyb/article/details/5870326

            因為wxWidgets 里已經include "Winsock.h"
            在網上找了解決方法:
            http://boost.2283326.n4.nabble.com/quot-WinSock-h-has-already-been-included-quot-problem-with-asio-and-VC-2010-td3574900.html
            兩種方法都可行

            "WinSock.h has already been included" : problem with asio and VC++2010

            Claude

            Hi!

            I use a boost asio library in my program. When I compile with Visual C++ obtain this error:

            [...]\boost_1_45_0\boost\asio\detail\socket_types.hpp(22): fatal error C1189: #error :  WinSock.h has already been included

            How can I fix this error?


            Reply | Threaded |   star

            Re: "WinSock.h has already been included" : problem with asio and VC++2010

            michi7x7-2

            > Hi!
            Hello,

            > I use a boost asio library in my program. When I compile with Visual C++
            > obtain this error:
            >
            > [...]\boost_1_45_0\boost\asio\detail\socket_types.hpp(22): fatal error
            > C1189: #error :  WinSock.h has already been included
            >
            > How can I fix this error?

            Try to include asio before including any other Windows-Headers, or use
            WinSock2.h instead of WinSock.

            Best Regards,

            michi7x7

            _______________________________________________
            Boost-users mailing list
            [hidden email]
            http://lists.boost.org/mailman/listinfo.cgi/boost-users
            Reply | Threaded |   star

            Re: "WinSock.h has already been included" : problem with asio and VC++2010

            Hee-young Kim
            In reply to this post by Claude
            If you use "Windows.h" library, set "#define WIN32_LEAN_AND_MEAN" in "stdafx.h" or a suitable place to avoid the duplication.

            from Hee-young
            Reply | Threaded |   star

            Re: "WinSock.h has already been included" : problem with asio and VC++2010

            Claude
            I solved the problem, thanks!

            posted @ 2012-04-05 13:25 多彩人生 閱讀(2706) | 評論 (0)編輯 收藏

            Double-checked locking真的有效嗎?

            Double-checked locking真的有效嗎?

            作者: zsxwing 日期: 2011-04-29 10:48:06

            在很多設計模式的書籍中,我們都可以看到類似下面的單例模式的實現代碼,一般稱為Double-checked locking(DCL)

            01public class Singleton {
            02 
            03    private static Singleton instance;
            04 
            05    private Singleton() {
            06        // do something
            07    }
            08 
            09    public static Singleton getInstance() {
            10        if (instance == null) {//1
            11            synchronized (Singleton.class) {//2
            12                if (instance == null) {//3
            13                    instance = new Singleton();//4
            14                }
            15            }
            16        }
            17        return instance;
            18    }
            19}

            這樣子的代碼看起來很完美,可以解決instance的延遲初始化。只是,事實往往不是如此。

            問題在于instance = new Singleton();這行代碼。

            在我們看來,這行代碼的意義大概是下面這樣子的

             

             

            	mem = allocate();             //收集內存 
            ctorSingleton(mem); //調用構造函數
            instance = mem; //把地址傳給instance
            	

             

            這行代碼在Java虛擬機(JVM)看來,卻可能是下面的三個步驟(亂序執行的機制):

             

            	mem = allocate();             //收集內存 
            instance = mem; //把地址傳給instance
            	ctorSingleton(instance);      //調用構造函數

             

            下面我們來假設一個場景。

            1. 線程A調用getInstance函數并且執行到//4。但是線程A只執行到賦值語句,還沒有調用構造函數。此時,instance已經不是null了,但是對象還沒有初始化。
            2. 很不幸線程A這時正好被掛起。
            3. 線程B獲得執行的權力,然后也開始調用getInstance。線程B在//1發現instance已經不是null了,于是就返回對象了,但是這個對象還沒有初始化,于是對這個對象進行操作就出錯了。

            問題就出在instance被提前初始化了。

            解決方案一,不使用延遲加載:

            01public class Singleton {
            02 
            03    private static Singleton instance = new Singleton();
            04 
            05    private Singleton() {
            06        // do something
            07    }
            08 
            09    public static Singleton getInstance() {
            10        return instance;
            11    }
            12}

            JVM內部的機制能夠保證當一個類被加載的時候,這個類的加載過程是線程互斥的。這樣當我們第一次調用getInstance的時候,JVM能夠幫我們保證instance只被創建一次,并且會保證把賦值給instance的內存初始化完畢。

            解決方案二,利用一個內部類來實現延遲加載:

            01public class Singleton {
            02 
            03    private Singleton() {
            04        // do something
            05    }
            06 
            07    private static class SingletonContainer {
            08        private static Singleton instance = new Singleton();
            09    }
            10 
            11    public static Singleton getInstance() {
            12        return SingletonContainer.instance;
            13    }
            14}

            這兩種方案都是利用了JVM的類加載機制的互斥。

            方案二的延遲加載實現是因為,只有在第一次調用Singleton.getInstance()函數時,JVM才會去加載SingletonContainer,并且初始化instance。

            不只Java存在這個問題,C/C++由于CPU的亂序執行機制,也同樣存在這樣的問題。

            抱歉,我之前的理解有誤,DCL在Java中失效的原因是JIT比較激進的優化導致的,在C/C++并不會由于CPU的亂序執行(調用構造函數和賦值這兩個操作對CPU來說絕對不會亂序的)產生這個問題。

            暫時不知道Java對于這個問題是否修復了。

            posted @ 2012-03-31 16:53 多彩人生 閱讀(320) | 評論 (0)編輯 收藏

            偉大架構師的秘密

            http://msdn.microsoft.com/zh-cn/library/aa480041.aspx

            所有偉大的架構師都掌握了在抽象的不同層次上概念化解決方案的技能。通過將解決方案組織到離散的層次,架構師可以專注于解決方案的單個方面而忽略所有剩余的復雜性。展示將抽象層次應用到 IT 解決方案的技術,并將其與其他工程學科相比較。

            一些架構師在這種復雜性方面明顯非常出色,而且在不斷進步。在我們的職業生涯中,能與一些真正偉大的分析師和架構師并肩工作是非常幸運的。反思這些經驗,我們已經分析出是什么造就了杰出的架構師。

            無 一例外,所有偉大的架構師都掌握了在截然不同的抽象層次上概念化解決方案的技能。通過將解決方案組織到離散的層次,架構師可以將精力集中在解決方案的單個 方面而忽略所有剩余的復雜性。他們一旦穩定了解決方案的某個部分,接下來就能繼續處理其他方面,從而不斷地將層次發展并完善到最終可以被實現的粘合模型 中。

            大多數軟件開發人員懂得應該將解決方案分解到抽象層次。但是在實際的項目中,這是非常難于付諸實踐的。當遇到第一個困難時,在急于開 始編碼時是很容易放棄這些層次的。偉大的架構師會經受這些挑戰并在整個項目的生命周期中嚴格保持這些層次。他們意識到,如果不這樣做,最終將淹沒在復雜性 中。


            posted @ 2012-03-31 11:05 多彩人生 閱讀(339) | 評論 (0)編輯 收藏

            boost::asio::deadline_timer

            注意deadline_timer和socket一樣,都用 io_service作為構造函數的參數。也即,在其上進行異步操作,都將導致和io_service所包含的iocp相關聯。這同樣意味著在析構 io_service之前,必須析構關聯在這個io_service上的deadline_timer。

            一個deadline_timer只維護一個超時時間,一個deadline_timer不同時維持多個定時器。

            void wait();
            void
            wait(boost::system::error_code & ec);

            這是個同步等待函數,例如:

            boost::asio::io_service io;
            boost::asio::deadline_timer t(io, boost::posix_time::seconds(5));
            t.wait();
            由于不涉及到異步,該函數和io_service沒什么關系。這個函數在windows下的實現就只是簡單的Sleep。因此也就不存在cancel之說。

            如果t的expire時間已過,那么t.wait會立刻返回。

            例如如下代碼:

            boost::asio::io_service io; 
            boost::asio::deadline_timer t(io, boost::posix_time::seconds(5));
            t.wait();
            t.wait();

            第一個t.wait會等待5s才返回,第2個t.wait會立刻返回。

            wait函數本身沒有參數,不存在t.wait(seconds(5))的用法。

            可以在構造deadline_timer時指定時間。

            basic_deadline_timer(
            boost::asio::io_service & io_service);

            basic_deadline_timer(
            boost::asio::io_service & io_service,
            const time_type & expiry_time);

            basic_deadline_timer(
            boost::asio::io_service & io_service,
            const duration_type & expiry_time);

            注意后兩種的區別。以下2種用法是等價的:

            boost::asio::deadline_timer t(io, boost::posix_time::microsec_clock::universal_time()+boost::posix_time::seconds(5));

            boost::asio::deadline_timer t(io, boost::posix_time::seconds(5));

            前者是絕對時間,后者是相對時間。

            除了在deadline_timer構造函數中指定時間,也可以使用如下2個函數指定時間:

            expires_at,expires_from_now。這兩個函數的區別是前者參數是絕對時間,后者是相對時間。例如:

            boost::asio::io_service io;

            boost::asio::deadline_timer t(io);

            t.expires_from_now(boost::posix_time::seconds(5));

            t.wait();

            注意這兩個函數除了設定下次超時時間之外,還有一個效果是取消前面所有的異步wait。詳情參看關于這兩個函數的詳細解釋。

            template<
                typename
            WaitHandler>
            void async_wait(
                WaitHandler handler);
            其中void handler(
            const boost::system::error_code& error // Result of operation.
            );

            注意這個error很重要,表明這個handler是因為超時被執行還是因為被cancel。
            符合2種情況之一,handler被執行:超時或者被cancel。
            這同時隱含的說明了除非io.stop被調用,否則handler一定會被執行。即便是被cancel。
            被cancel有多種方法,直接調用cancel或者調用expires_at,expires_from_now重新設置超時時間。
            void handle_wait(const boost::system::error_code& error,
            boost::asio::deadline_timer& t,int& count)
            {
            if(!error)
            {
            std::cout<< count<<"\n";
            if(count++<5)
            {
            t.expires_from_now(boost::posix_time::seconds(1));
            t.async_wait(boost::bind(handle_wait,boost::asio::placeholders::error,
            boost::ref(t),boost::ref(count)));
            }
            }
            }

            int main()
            {
            boost::asio::io_service io;
            boost::asio::deadline_timer t(io);
            size_t a = t.expires_from_now(boost::posix_time::seconds(1));
            int count = 0;
            t.async_wait(boost::bind(handle_wait,boost::asio::placeholders::error,
            boost::ref(t),boost::ref(count)));
            io.run();
            return 0;
            }

            deadline_timer的析構函數什么也不做,因此不會導致發出的async_wait被cancel。

            std::size_t cancel();

            std::size_t
            cancel(
                boost::system::error_code & ec);
            此函數調用會導致所有尚未返回的async_wait(handler)的handler被調用,同時error_code為boost::asio::error::operation_aborted。返回值是被cancel的timer數量。

             time_type expires_at() const;

            std::size_t
            expires_at(
            const time_type & expiry_time);

            std::size_t
            expires_at(
            const time_type & expiry_time,
            boost::system::error_code & ec);
            duration_type expires_from_now() const;

            std::size_t
            expires_from_now(
            const duration_type & expiry_time);

            std::size_t
            expires_from_now(
            const duration_type & expiry_time,
            boost::system::error_code & ec);
            以上2組函數用來設置新的超時時間,同時cancel所有未完成的async_wait操作。注意這兩個函數的返回值即為cancel的操作數量。
            考慮如下場景,我們有一個workerthread正在調用io_work.run();

            此時主線程向workerthread發出了一個異步調用,例如post(...),考慮到io_work.run很可能積壓了很多handlers沒有處理,或者某些handlers處理非常耗時,希望它在5s內必須返回。那么可以:

            void handle_wait(const boost::system::error_code& error,bool& Ret)
            {
                if(!error) Ret = false;
            }

            void handle_func(
                boost::shared_ptr<boost::asio::deadline_timer> t,
                boost::shared_ptr<boost::asio::io_service> io,
                int* v)
            {
                boost::asio::io_service::work work(*io);

                if(t->cancel()>0)
                {       
                    *v = 1;
                }
            }

            void func_delay_1_second()
            {
                boost::asio::io_service io;
                boost::asio::deadline_timer t(io,boost::posix_time::seconds(1));
                t.wait();
            }

            bool sync_func(int& v,boost::asio::io_service& io_work)
            {
                boost::shared_ptr<boost::asio::io_service> io(new boost::asio::io_service);
                boost::shared_ptr<boost::asio::deadline_timer> t(new boost::asio::deadline_timer(*io));
                t->expires_from_now(boost::posix_time::seconds(5));
                bool ret = true;
                t->async_wait(boost::bind(handle_wait,boost::asio::placeholders::error,boost::ref(ret)));
                io_work.post(boost::bind(handle_func,t,io,&v));
                io->run();
                return ret;
            }

            int main()
            {
                boost::asio::io_service io_work;
                auto_ptr<boost::asio::io_service::work> work(new boost::asio::io_service::work(io_work));
                boost::thread workthread(boost::bind(&boost::asio::io_service::run, &io_work));
                for(int i=0;i<3;++i) io_work.post(func_delay_1_second);

                int v = 0;
                bool ret = sync_func(v,io_work);
                if(ret) printf("v %d\n",v);

                work.reset();
                workthread.join();
                return 0;
            }

            上面代碼中如果先進入handle_wait,則表明超時,此時設置ret = false,然后io.run會退出,表明調用失敗,如果稍后進入handle_func,則t->cancel會返回0,也不做任何操作。雖然在 io.run退出時會釋放v,但由于handle_func不做任何操作因此也不會引起任何安全問題。如果handle_func先進入,則首先使用 work讓io.run不會退出,然后取消timer,并且設置,隨后work析構,io.run會退出。注意這里面的同步問題:如果先進入 handle_wait,隨后進入handle_func,那么handle_func中的t->cancel會返回0從而不做任何事。如果先進入 handle_func,隨后進入handle_wait,那么t->cancel或者返回0或者返回1,由于使用了work,io.run也不會 退出。注意這里的t和io都是shared_ptr的,否則因為如果handle_wait先返回,則io.run會立刻退出并析 構,handle_func中將使用懸空的t和io,將導致非法操作。注意這里的io必須是shared_ptr的,如果 boost::asio::io_service::work work(*io); 改成work(t->get_ioservice());則t是有效的,而t所索引的io_service已經無效了,同樣會導致非法操作。牢記 io_service的使用原則:必須首先析構所有索引的其他對象之后才能析構io_service。

            posted @ 2012-03-30 16:39 多彩人生 閱讀(2260) | 評論 (1)編輯 收藏

            RAII

             RAII是“資源獲取就是初始化”的縮語(Resource Acquisition Is Initialization),是一種利用對象生命周期來控制程序資源(如內存、文件句柄、網絡連接、互斥量等等)的簡單技術。   RAII 的一般做法是這樣的:在對象構造時獲取資源,接著控制對資源的訪問使之在對象的生命周期內始終保持有效,最后在對象析構的時候釋放資源。借此,我們實際上把管理一份資源的責任托管給了一個對象。這種做法有兩大好處:   1,我們不需要顯式地釋放資源。   2,采用這種方式,對象所需的資源在其生命期內始終保持有效 —— 我們可以說,此時這個類維護了一個 invariant。這樣,通過該類對象使用資源時,就不必檢查資源有效性的問題,可以簡化邏輯、提高效率。

            posted @ 2012-03-29 21:20 多彩人生 閱讀(225) | 評論 (0)編輯 收藏

            wxWidgets

            安裝好以后首先要編譯。

            1、   登陸http://www.wxwidgets.org/,下載wxMSW-2.8.8-Setup.exe

            2、   運行wxMSW-2.8.8-Setup.exe,將wxWidgets安裝到D:\wxWidgets-2.8.8

            3、   安裝完畢后還需要進行編譯,要求有IDE,我用的是MS Visual Studio 2008

            4、   進入D:\wxWidgets-2.8.8\build\msw,運用MS Visual Studio 2008打開wx.dsw或者wx_dll.dsw(或者兩者都編譯),因為.dsw文件是vc6的工程文件,點確定將所有文件進行轉換,然后點擊Build->Configuration Manager,彈出窗口,選擇Active solution configurationUnicode Debug或是別的,如果需要其中多個solution configuration,可以依次選中,然后依次按下F7Build solution,我分別選中了Unicode DebugUnicode Release,編譯完成后會在D:\wxWidgets-2.8.8\lib下生成vc_lib文件夾,其中包括生成的相應的.lib等文件和 mswud文件夾。到此,wxWidgets安裝完畢。

            【注意】wxbase28ud.lib中的ud代表Unicode Dug版本,相應地wxbase28u.lib中的u代表的是UnicodeRelease版本。Unicode是統一的字符編碼標準,采用雙字節對字符進行編碼,支持多語言,有利于國際化,處理更方便,所以選擇編譯成Unicode版本。


            工程中需要添加 wxWidget 的頭文件目錄:

            %installdir%\include\msvc
            %installdir%\include

            以及庫目錄:

            %installdir%\lib\vc_lib

            另外如果是普通 Win32 工程的話,還需要鏈接額外的庫:

            comctl32.lib rpcrt4.lib 

            posted @ 2012-03-29 16:48 多彩人生 閱讀(376) | 評論 (0)編輯 收藏

            stdio.h cstdio

               #include<cstdio>  

            2010-01-26 23:25:29|  分類: 編程 |字號 訂閱

            在新的C++標準中,生成新頭文件 的方法僅僅是將現有C++頭文件名中的.h去掉。例如,<iostream.h>變成了< iostream>,<complex.h>變成了<complex>,等等。對于C頭文件,采用同樣的方法,但在每個名 字前還要添加一個c。所以C的<string.h>變成了<cstring>,<stdio.h>變成了< cstdio>,等等。    
              舊的C++頭文件是官方所反對使用的(即,明確列出不再支持),但舊的C頭文件則沒有(以保持對C的兼容性)。    
              下面是C++頭文件的現狀:    
              ·     舊的C++頭文件名如<iostream.h>將會繼續被支持,盡管它們不在官方標準中。這些頭文件的內容不在名字空間std中。    
              ·     新的C++頭文件如<iostream>包含的基本功能和對應的舊頭文件相同,但頭文件的內容在名字空間std中。(在標準化的過程中,庫中有些部分的細節被修改了,所以舊頭文件和新頭文件中的實體不一定完全對應。)    
              ·     標準C頭文件如<stdio.h>繼續被支持。頭文件的內容不在std中。    
              ·     具有C庫功能的新C++頭文件具有如<cstdio>這樣的名字。它們提供的內容和相應的舊C頭文件相同,只是內容在std中。

            如果編譯器同時支持<iostream>和  
              <iostream.h>   。如果使用了#include  
              <iostream>,   得到的是置于名字空間std下的iostream   庫的元素;  
              如果使用#include   <iostream.h>,得到的是置于全局空間的同樣的元素。在全  
              局空間獲取元素會導致名字沖突,而設計名字空間的初衷正是用來避免這種名  
              字沖突的發生.
            #if           _MSC_VER   >   1000  
              #pragma   on
            ce  
              #endif  
               
              #ifndef   _CSTDIO_  
              #define   _CSTDIO_  
              #ifdef   _STD_USING  
                #undef   _STD_USING  
                #include   <stdio.h>  
                #define   _STD_USING  
              #else  
                #include   <stdio.h>  
              #endif   /*   _STD_USING   */  
              #endif   /*   _CSTDIO_   */  
               
              上面就是cstdio的全部內容(vc6)  
              好像只是include   <stdio.h>而已?。。?/div>

            posted @ 2012-03-29 16:38 多彩人生 閱讀(493) | 評論 (0)編輯 收藏

            僅列出標題
            共25頁: First 17 18 19 20 21 22 23 24 25 

            導航

            統計

            • 隨筆 - 244
            • 文章 - 0
            • 評論 - 21
            • 引用 - 0

            常用鏈接

            留言簿(3)

            隨筆分類

            隨筆檔案

            搜索

            •  

            最新評論

            閱讀排行榜

            評論排行榜

            成人国内精品久久久久一区| 久久天天躁狠狠躁夜夜躁2O2O| 国产精品久久久久jk制服| 色综合久久中文字幕无码| 国产成人综合久久精品尤物| 午夜欧美精品久久久久久久| 久久综合九色综合97_久久久| 99久久夜色精品国产网站| 久久精品视频91| 97精品国产97久久久久久免费| 人妻少妇久久中文字幕一区二区 | 开心久久婷婷综合中文字幕| 丰满少妇高潮惨叫久久久| 久久久青草青青国产亚洲免观| 潮喷大喷水系列无码久久精品| 久久久久无码精品| 欧美精品一本久久男人的天堂| 精品无码久久久久国产动漫3d| 欧美亚洲国产精品久久久久| 久久99精品国产麻豆婷婷| 久久99精品免费一区二区| 久久综合九色综合网站 | 久久精品国产99国产精品亚洲| 久久国产精品国产自线拍免费| 狠狠色丁香久久婷婷综| 久久久久久曰本AV免费免费| 久久高潮一级毛片免费| 亚洲成色999久久网站| 国产精品久久久久AV福利动漫| 久久只有这精品99| 色综合久久中文字幕综合网| 久久天天躁夜夜躁狠狠| 欧美日韩精品久久久久| 久久精品这里只有精99品| 久久这里只有精品首页| 97久久超碰成人精品网站| 久久久WWW免费人成精品| 91精品国产色综久久| 亚洲伊人久久大香线蕉苏妲己| 狠狠干狠狠久久| 国产亚州精品女人久久久久久 |