• <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>

            Where there is a dream ,there is hope

              C++博客 :: 首頁 :: 聯(lián)系 :: 聚合  :: 管理
              64 Posts :: 0 Stories :: 8 Comments :: 0 Trackbacks

            常用鏈接

            留言簿(1)

            我參與的團(tuán)隊(duì)

            搜索

            •  

            最新評論

            閱讀排行榜

            評論排行榜

            #

            盡管函數(shù)指針被廣泛用于實(shí)現(xiàn)函數(shù)回調(diào),但C++還提供了一個(gè)重要的實(shí)現(xiàn)回調(diào)函數(shù)的方法,那就是函數(shù)對象。函數(shù)對象(也稱“算符”)是重載了“()”操作符的普通類對象。因此從語法上講,函數(shù)對象與普通的函數(shù)行為類似。

                    用函數(shù)對象代替函數(shù)指針有幾個(gè)優(yōu)點(diǎn),首先,因?yàn)閷ο罂梢栽趦?nèi)部修改而不用改動外部接口,因此設(shè)計(jì)更靈活,更富有彈性。函數(shù)對象也具備有存儲先前調(diào)用結(jié)果的數(shù)據(jù)成員。在使用普通函數(shù)時(shí)需要將先前調(diào)用的結(jié)果存儲在全程或者本地靜態(tài)變量中,但是全程或者本地靜態(tài)變量有某些我們不愿意看到的缺陷。
                    其次,在函數(shù)對象中編譯器能實(shí)現(xiàn)內(nèi)聯(lián)調(diào)用,從而更進(jìn)一步增強(qiáng)了性能。這在函數(shù)指針中幾乎是不可能實(shí)現(xiàn)的。

            下面舉例說明如何定義和使用函數(shù)對象。首先,聲明一個(gè)普通的類并重載“()”操作符:

            class Negate 
            {
            public: 
            int operator() (int n) { return -n;} 
            };

                    重載操作語句中,記住第一個(gè)圓括弧總是空的,因?yàn)樗碇剌d的操作符名;第二個(gè)圓括弧是參數(shù)列表。一般在重載操作符時(shí),參數(shù)數(shù)量是固定的,而重載“()” 操作符時(shí)有所不同,它可以有任意多個(gè)參數(shù)。

                    因?yàn)樵贜egate中內(nèi)建的操作是一元的(只有一個(gè)操作數(shù)),重載的“()”操作符也只有一個(gè)參數(shù)。返回類型與參數(shù)類型相同-本例中為int。函數(shù)返回與參數(shù)符號相反的整數(shù)。

            使用函數(shù)對象

                    我們現(xiàn)在定義一個(gè)叫Callback()的函數(shù)來測試函數(shù)對象。Callback()有兩個(gè)參數(shù):一個(gè)為int一個(gè)是對類Negate的引用。 Callback()將函數(shù)對象neg作為一個(gè)普通的函數(shù)名:

            #include <iostream>
            using std::cout;

            void Callback(int n, Negate & neg) 
            {
            int val = neg(n); //調(diào)用重載的操作符“()” 
            cout << val;
            }

            不要的代碼中,注意neg是對象,而不是函數(shù)。編譯器將語句

            int val = neg(n);

            轉(zhuǎn)化為

            int val = neg.operator()(n);

                    通常,函數(shù)對象不定義構(gòu)造函數(shù)和析構(gòu)函數(shù)。因此,在創(chuàng)建和銷毀過程中就不會發(fā)生任何問題。前面曾提到過,編譯器能內(nèi)聯(lián)重載的操作符代碼,所以就避免了與函數(shù)調(diào)用相關(guān)的運(yùn)行時(shí)問題。

            為了完成上面?zhèn)€例子,我們用主函數(shù)main()實(shí)現(xiàn)Callback()的參數(shù)傳遞:

            int main() 
            {
            Callback(5, Negate() ); //輸出 -5
            }

            本例傳遞整數(shù)5和一個(gè)臨時(shí)Negate對象到Callback(),然后程序輸出-5。

            模板函數(shù)對象

                    從上面的例子中可以看出,其數(shù)據(jù)類型被限制在int,而通用性是函數(shù)對象的優(yōu)勢之一,如何創(chuàng)建具有通用性的函數(shù)對象呢?方法是使用模板,也就是將重載的操作符“()”定義為類成員模板,以便函數(shù)對象適用于任何數(shù)據(jù)類型:如double,_int64或char:

            class GenericNegate
            {
            public: 
            template <class T> T operator() (T t) const {return -t;}
            };

            int main()
            {
            GenericNegate negate;
            cout<< negate(5.3333); // double
            cout<< negate(10000000000i64); // __int64
            }

            如果用普通的回調(diào)函數(shù)實(shí)現(xiàn)上述的靈活性是相當(dāng)困難的。

            標(biāo)準(zhǔn)庫中函數(shù)對象

                    C++標(biāo)準(zhǔn)庫定義了幾個(gè)有用的函數(shù)對象,它們可以被放到STL算法中。例如,sort()算法以
            判斷對象(predicate object)作為其第三個(gè)參數(shù)。判斷對象是一個(gè)返回Boolean型結(jié)果的
            模板化的函數(shù)對象。可以向sort()傳遞greater<>或者less<>來強(qiáng)行實(shí)現(xiàn)排序的升序或降序:

            #include <functional> // for greater<> and less<>
            #include <algorithm> //for sort() 
            #include <vector>
            using namespace std;

            int main()

            vector <int> vi;
            //..填充向量
            sort(vi.begin(), vi.end(), greater<int>() );//降序( descending )
            sort(vi.begin(), vi.end(), less<int>() ); //升序 ( ascending )
            }

            posted @ 2011-06-29 18:10 IT菜鳥 閱讀(94) | 評論 (0)編輯 收藏

            用C++的stl庫,相信大家都有用vector的經(jīng)歷,畢竟vector支持直接下標(biāo)方式取數(shù)據(jù)的確方便很多。

            但是vector默認(rèn)是不提供find方法的,所以我們在查找的時(shí)候,通常這樣寫代碼:

            vector<int> vec;
            for(unsigned int i = 0;i<vec.size();++i)
            {
                if(vec[i]==xxx)
                {
                    break;
                }
            }

            并不是說提供不了,而是stl庫中實(shí)際上已經(jīng)有通用的find函數(shù)(不止find……)

            可以看一下下面的代碼:

            int main(int argc,char* argv[])
            {
                vector<int> vec;
                vec.push_back(123);
                vec.push_back(456);
                vector<int>::iterator findit = find(vec.begin(),vec.end(),123);
                //vector<int>::iterator findit = find(vec.begin(),vec.end(),111);
                if(findit==vec.end())
                {
                    printf("no find\n");
                }
                else
                {
                    printf("find[%d]\n",*findit);
                }
                return 0;
            }

            這樣的寫法會不會簡單很多呢?
            需要說明的是,雖然這個(gè)通用的find方法也是可以用在map,set等上面的,但是效率會比容器內(nèi)部的find方法慢很多,所以,除非容器實(shí)在是沒有提供find方法,否則還是建議不要用公共的這一種。

            另外,作為題外話,我們需要注意一下vector的刪除(erase)操作。由于vector需要能以下標(biāo)方式取數(shù)據(jù),所以必須時(shí)刻保證連續(xù)的存儲空間,對應(yīng)于實(shí)現(xiàn)上,即,當(dāng)刪除vector中間的一個(gè)成員時(shí),這個(gè)成員后面的所有成員,會以原順序向前全部拷貝過來。有興趣的朋友,可以用這個(gè)例子測試一下。
            這里起碼告訴了我們兩件事:

            1.vector中一個(gè)成員被刪除,會導(dǎo)致后面的成員進(jìn)行copy和析構(gòu)操作。
            2.vector不適合做有大量插入刪除操作的容器,因?yàn)榭截悆?nèi)存本身浪費(fèi)很大

            OK,到此為止啦~

            posted @ 2011-06-22 15:35 IT菜鳥 閱讀(2381) | 評論 (0)編輯 收藏

            之前寫查找一個(gè)VECTOR中保存的一個(gè)結(jié)構(gòu)的時(shí)候,知道其中的一個(gè)數(shù)據(jù)成員,每次都是遍歷一遍,寫久了覺得好麻煩,覺得不應(yīng)該是這樣才對。果真在網(wǎng)上找到了這個(gè)方法:

            用boost::bind,非常簡單:

            find_if(v.begin(),v.end(),bind(&A::id,_1)==25);


            如果需要,下面是完整示例代碼:

            #include   <algorithm>
            #include   <vector>
            #include   <boost/bind.hpp>

            struct   A
            {
                int   id;
            };

            int   main()
            {
                using   namespace   std;
                using   namespace   boost;
                vector <A>   v;
                find_if(v.begin(),v.end(),bind(&A::id,_1)==25);
            }

            //bind用法



            posted @ 2011-06-22 15:34 IT菜鳥 閱讀(1776) | 評論 (0)編輯 收藏

            // general version
            template<class T>
            class Compare
            {
            public:
            static bool IsEqual(const T& lh, const T& rh)
            {
            return lh == rh;
            }
            };

                這是一個(gè)用于比較的類模板,里面可以有多種用于比較的函數(shù), 以IsEqual為例。

                一、特化為絕對類型

                也就是說直接為某個(gè)特定類型做特化,這是我們最常見的一種特化方式, 如特化為float, double等

             // specialize for float
            template<>
            class Compare<float>
            {
            public:
            static bool IsEqual(const float& lh, const float& rh)
            {
            return abs(lh - rh) < 10e-3;
            }
            };

            // specialize for double
            template<>
            class Compare<double>
            {
            public:
            static bool IsEqual(const double& lh, const double& rh)
            {
            return abs(lh - rh) < 10e-6;
            }
            };

                二、特化為引用,指針類型

                這種特化我最初是在stl源碼的的iterator_traits特化中發(fā)現(xiàn)的, 如下:

             template <class _Iterator>
            struct iterator_traits {
            typedef typename _Iterator::iterator_category iterator_category;
            typedef typename _Iterator::value_type value_type;
            typedef typename _Iterator::difference_type difference_type;
            typedef typename _Iterator::pointer pointer;
            typedef typename _Iterator::reference reference;
            };

            // specialize for _Tp*
            template <class _Tp>
            struct iterator_traits<_Tp*> {
            typedef random_access_iterator_tag iterator_category;
            typedef _Tp value_type;
            typedef ptrdiff_t difference_type;
            typedef _Tp* pointer;
            typedef _Tp& reference;
            };

            // specialize for const _Tp*
            template <class _Tp>
            struct iterator_traits<const _Tp*> {
            typedef random_access_iterator_tag iterator_category;
            typedef _Tp value_type;
            typedef ptrdiff_t difference_type;
            typedef const _Tp* pointer;
            typedef const _Tp& reference;
            };

                當(dāng)然,除了T*, 我們也可以將T特化為 const T*, T&, const T&等,以下還是以T*為例:
             // specialize for T*
            template<class T>
            class Compare<T*>
            {
            public:
            static bool IsEqual(const T* lh, const T* rh)
            {
            return Compare<T>::IsEqual(*lh, *rh);
            }
            };

                這種特化其實(shí)是就不是一種絕對的特化, 它只是對類型做了某些限定,但仍然保留了其一定的模板性,這種特化給我們提供了極大的方便, 如這里, 我們就不需要對int*, float*, double*等等類型分別做特化了。

                三、特化為另外一個(gè)類模板

                這其實(shí)是第二種方式的擴(kuò)展,其實(shí)也是對類型做了某種限定,而不是絕對化為某個(gè)具體類型,如下:
             // specialize for vector<T>
            template<class T>
            class Compare<vector<T> >
            {
            public:
            static bool IsEqual(const vector<T>& lh, const vector<T>& rh)
            {
            if(lh.size() != rh.size()) return false;
            else
            {
            for(int i = 0; i < lh.size(); ++i)
            {
            if(lh[i] != rh[i]) return false;
            }
            }
            return true;
            }
            };

                這就把IsEqual的參數(shù)限定為一種vector類型, 但具體是vector<int>還是vector<float>, 我們可以不關(guān)心, 因?yàn)閷τ谶@兩種類型,我們的處理方式是一樣的,我們可以把這種方式稱為“半特化”。

                當(dāng)然, 我們可以將其“半特化”為任何我們自定義的模板類類型:
             // specialize for any template class type
            template <class T1>
            struct SpecializedType
            {
            T1 x1;
            T1 x2;
            };
            template <class T>
            class Compare<SpecializedType<T> >
            {
            public:
            static bool IsEqual(const SpecializedType<T>& lh, const SpecializedType<T>& rh)
            {
            return Compare<T>::IsEqual(lh.x1 + lh.x2, rh.x1 + rh.x2);
            }
            };

                這就是三種類型的模板特化, 我們可以這么使用這個(gè)Compare類:

             // int
            int i1 = 10;
            int i2 = 10;
            bool r1 = Compare<int>::IsEqual(i1, i2);

            // float
            float f1 = 10;
            float f2 = 10;
            bool r2 = Compare<float>::IsEqual(f1, f2);

            // double
            double d1 = 10;
            double d2 = 10;
            bool r3 = Compare<double>::IsEqual(d1, d2);

            // pointer
            int* p1 = &i1;
            int* p2 = &i2;
            bool r4 = Compare<int*>::IsEqual(p1, p2);

            // vector<T>
            vector<int> v1;
            v1.push_back(1);
            v1.push_back(2);

            vector<int> v2;
            v2.push_back(1);
            v2.push_back(2);
            bool r5 = Compare<vector<int> >::IsEqual(v1, v2);

            // custom template class
            SpecializedType<float> s1 = {10.1f,10.2f};
            SpecializedType<float> s2 = {10.3f,10.0f};
            bool r6 = Compare<SpecializedType<float> >::IsEqual(s1, s2);


                模板有兩種特化,全特化和偏特化(局部特化)

                模板函數(shù)只能全特化,沒有偏特化(以后可能有)。

                模板類是可以全特化和偏特化的。

                全特化,就是模板中模板參數(shù)全被指定為確定的類型。

                全特化也就是定義了一個(gè)全新的類型,全特化的類中的函數(shù)可以與模板類不一樣。

                偏特化,就是模板中的模板參數(shù)沒有被全部確定,需要編譯器在編譯時(shí)進(jìn)行確定。

                在類型上加上const、&、*( cosnt int、int&、int*、等等)并沒有產(chǎn)生新的類型。只是類型被修飾了。模板在編譯時(shí),可以得到這些修飾信息。

                模板的特化是非常有用的。它像一個(gè)在編譯期的條件判斷。當(dāng)編譯器在編譯時(shí)找到了符合的特化實(shí)現(xiàn),就會使用這個(gè)特化實(shí)現(xiàn)。這就叫編譯器多態(tài)(或者叫靜態(tài)多態(tài))。這種東西對編寫基礎(chǔ)庫是很有用的。這也就是為何c++的基礎(chǔ)庫大量使用了模板技術(shù),而且大量使用了特化,特別是偏特化。

                在泛型中,利用特化類得到類新的特性,以便找到最適合這種特性的實(shí)現(xiàn)。而這一切都是在編譯時(shí)完成。

            posted @ 2011-06-16 18:26 IT菜鳥 閱讀(512) | 評論 (0)編輯 收藏

            C++箴言:理解typename的兩個(gè)含義  問題:在下面的 template declarations(模板聲明)中 class 和 typename 有什么不同?
            template<class T> class Widget; // uses "class"
            template<typename T> class Widget; // uses "typename"
              答案:沒什么不同。在聲明一個(gè) template type parameter(模板類型參數(shù))的時(shí)候,class 和 typename 意味著完全相同的東西。一些程序員更喜歡在所有的時(shí)間都用 class,因?yàn)樗菀纵斎搿F渌耍òㄎ冶救耍└矚g typename,因?yàn)樗凳局@個(gè)參數(shù)不必要是一個(gè) class type(類類型)。少數(shù)開發(fā)者在任何類型都被允許的時(shí)候使用 typename,而把 class 保留給僅接受 user-defined types(用戶定義類型)的場合。但是從 C++ 的觀點(diǎn)看,class 和 typename 在聲明一個(gè) template parameter(模板參數(shù))時(shí)意味著完全相同的東西。

              然而,C++ 并不總是把 class 和 typename 視為等同的東西。有時(shí)你必須使用 typename。為了理解這一點(diǎn),我們不得不討論你會在一個(gè) template(模板)中涉及到的兩種名字。

              假設(shè)我們有一個(gè)函數(shù)的模板,它能取得一個(gè) STL-compatible container(STL 兼容容器)中持有的能賦值給 ints 的對象。進(jìn)一步假設(shè)這個(gè)函數(shù)只是簡單地打印它的第二個(gè)元素的值。它是一個(gè)用糊涂的方法實(shí)現(xiàn)的糊涂的函數(shù),而且就像我下面寫的,它甚至不能編譯,但是請將這些事先放在一邊——有一種方法能發(fā)現(xiàn)我的愚蠢:
            template<typename C> // print 2nd element in
            void print2nd(const C& container) // container;

             
            // this is not valid C++!
             if (container.size() >= 2{
              C::const_iterator iter(container.begin()); 
            // get iterator to 1st element
              ++iter; // move iter to 2nd element
              int value = *iter; // copy that element to an int
              std::cout << value; // print the int
             }

            }
              我突出了這個(gè)函數(shù)中的兩個(gè) local variables(局部變量),iter 和 value。iter 的類型是 C::const_iterator,一個(gè)依賴于 template parameter(模板參數(shù))C 的類型。一個(gè) template(模板)中的依賴于一個(gè) template parameter(模板參數(shù))的名字被稱為 dependent names(依賴名字)。當(dāng)一個(gè) dependent names(依賴名字)嵌套在一個(gè) class(類)的內(nèi)部時(shí),我稱它為 nested dependent name(嵌套依賴名字)。C::const_iterator 是一個(gè) nested dependent name(嵌套依賴名字)。實(shí)際上,它是一個(gè) nested dependent type name(嵌套依賴類型名),也就是說,一個(gè)涉及到一個(gè) type(類型)的 nested dependent name(嵌套依賴名字)。

              print2nd 中的另一個(gè) local variable(局部變量)value 具有 int 類型。int 是一個(gè)不依賴于任何 template parameter(模板參數(shù))的名字。這樣的名字以 non-dependent names(非依賴名字)聞名。(我想不通為什么他們不稱它為 independent names(無依賴名字)。如果,像我一樣,你發(fā)現(xiàn)術(shù)語 "non-dependent" 是一個(gè)令人厭惡的東西,你就和我產(chǎn)生了共鳴,但是 "non-dependent" 就是這類名字的術(shù)語,所以,像我一樣,轉(zhuǎn)轉(zhuǎn)眼睛放棄你的自我主張。)

              nested dependent name(嵌套依賴名字)會導(dǎo)致解析困難。例如,假設(shè)我們更加愚蠢地以這種方法開始 print2nd:
            template<typename C>
            void print2nd(const C& container)
            {
             C::const_iterator 
            * x;
             
            //
            }
              這看上去好像是我們將 x 聲明為一個(gè)指向 C::const_iterator 的 local variable(局部變量)。但是它看上去如此僅僅是因?yàn)槲覀冎?C::const_iterator 是一個(gè) type(類型)。但是如果 C::const_iterator 不是一個(gè) type(類型)呢?如果 C 有一個(gè) static data member(靜態(tài)數(shù)據(jù)成員)碰巧就叫做 const_iterator 呢?再如果 x 碰巧是一個(gè) global variable(全局變量)的名字呢?在這種情況下,上面的代碼就不是聲明一個(gè) local variable(局部變量),而是成為 C::const_iterator 乘以 x!當(dāng)然,這聽起來有些愚蠢,但它是可能的,而編寫 C++ 解析器的人必須考慮所有可能的輸入,甚至是愚蠢的。

              直到 C 成為已知之前,沒有任何辦法知道 C::const_iterator 到底是不是一個(gè) type(類型),而當(dāng) template(模板)print2nd 被解析的時(shí)候,C 還不是已知的。C++ 有一條規(guī)則解決這個(gè)歧義:如果解析器在一個(gè) template(模板)中遇到一個(gè) nested dependent name(嵌套依賴名字),它假定那個(gè)名字不是一個(gè) type(類型),除非你用其它方式告訴它。缺省情況下,nested dependent name(嵌套依賴名字)不是 types(類型)。(對于這條規(guī)則有一個(gè)例外,我待會兒告訴你。)

              記住這個(gè),再看看 print2nd 的開頭:
            template<typename C>
            void print2nd(const C& container)
            {
             
            if (container.size() >= 2) {
              C::const_iterator iter(container.begin()); 
            // this name is assumed to
               // not be a type
              這為什么不是合法的 C++ 現(xiàn)在應(yīng)該很清楚了。iter 的 declaration(聲明)僅僅在 C::const_iterator 是一個(gè) type(類型)時(shí)才有意義,但是我們沒有告訴 C++ 它是,而 C++ 就假定它不是。要想轉(zhuǎn)變這個(gè)形勢,我們必須告訴 C++ C::const_iterator 是一個(gè) type(類型)。我們將 typename 放在緊挨著它的前面來做到這一點(diǎn):
            template<typename C> // this is valid C++
            void print2nd(const C& container)
            {
            if (container.size() >= 2) {
            typename C::const_iterator iter(container.begin());

            }
            }
              通用的規(guī)則很簡單:在你涉及到一個(gè)在 template(模板)中的 nested dependent type name(嵌套依賴類型名)的任何時(shí)候,你必須把單詞 typename 放在緊挨著它的前面。(重申一下,我待會兒要描述一個(gè)例外。)

              typename 應(yīng)該僅僅被用于標(biāo)識 nested dependent type name(嵌套依賴類型名);其它名字不應(yīng)該用它。例如,這是一個(gè)取得一個(gè) container(容器)和這個(gè) container(容器)中的一個(gè) iterator(迭代器)的 function template(函數(shù)模板):
            template<typename C> // typename allowed (as is "class")
            void f(const C& container, // typename not allowed
            typename C::iterator iter); // typename required
              C 不是一個(gè) nested dependent type name(嵌套依賴類型名)(它不是嵌套在依賴于一個(gè) template parameter(模板參數(shù))的什么東西內(nèi)部的),所以在聲明 container 時(shí)它不必被 typename 前置,但是 C::iterator 是一個(gè) nested dependent type name(嵌套依賴類型名),所以它必需被 typename 前置。

              "typename must precede nested dependent type names"(“typename 必須前置于嵌套依賴類型名”)規(guī)則的例外是 typename 不必前置于在一個(gè) list of base classes(基類列表)中的或者在一個(gè) member initialization list(成員初始化列表)中作為一個(gè) base classes identifier(基類標(biāo)識符)的 nested dependent type name(嵌套依賴類型名)。例如:
            template<typename T>
            class Derived: public Base<T>::Nested { 
             
            // base class list: typename not
             public// allowed
              explicit Derived(int x)
              : Base
            <T>::Nested(x) // base class identifier in mem
              { 
               
            // init. list: typename not allowed
             
               typename Base
            <T>::Nested temp; // use of nested dependent type
                // name not in a base class list or
              } // as a base class identifier in a
               // mem. init. list: typename required
            };
              這樣的矛盾很令人討厭,但是一旦你在經(jīng)歷中獲得一點(diǎn)經(jīng)驗(yàn),你幾乎不會在意它。

              讓我們來看最后一個(gè) typename 的例子,因?yàn)樗谀憧吹降恼鎸?shí)代碼中具有代表性。假設(shè)我們在寫一個(gè)取得一個(gè) iterator(迭代器)的 function template(函數(shù)模板),而且我們要做一個(gè) iterator(迭代器)指向的 object(對象)的局部拷貝 temp,我們可以這樣做:
            template<typename IterT>
            void workWithIterator(IterT iter)
            {
             typename std::iterator_traits
            <IterT>::value_type temp(*iter);
             
            }
              不要讓 std::iterator_traits<IterT>::value_type 嚇倒你。那僅僅是一個(gè) standard traits class(標(biāo)準(zhǔn)特性類)的使用,用 C++ 的說法就是 "the type of thing pointed to by objects of type IterT"(“被類型為 IterT 的對象所指向的東西的類型”)。這個(gè)語句聲明了一個(gè)與 IterT objects 所指向的東西類型相同的 local variable(局部變量)(temp),而且用 iter 所指向的 object(對象)對 temp 進(jìn)行了初始化。如果 IterT 是 vector<int>::iterator,temp 就是 int 類型。如果 IterT 是 list<string>::iterator,temp 就是 string 類型。因?yàn)?std::iterator_traits<IterT>::value_type 是一個(gè) nested dependent type name(嵌套依賴類型名)(value_type 嵌套在 iterator_traits<IterT> 內(nèi)部,而且 IterT 是一個(gè) template parameter(模板參數(shù))),我們必須讓它被 typename 前置。

              如果你覺得讀 std::iterator_traits<IterT>::value_type 令人討厭,就想象那個(gè)與它相同的東西來代表它。如果你像大多數(shù)程序員,對多次輸入它感到恐懼,那么你就需要創(chuàng)建一個(gè) typedef。對于像 value_type 這樣的 traits member names(特性成員名),一個(gè)通用的慣例是 typedef name 與 traits member name 相同,所以這樣的一個(gè) local typedef 通常定義成這樣:
            template<typename IterT>
            void workWithIterator(IterT iter)
            {
             typedef typename std::iterator_traits
            <IterT>::value_type value_type;

             value_type temp(
            *iter);
             
            }
              很多程序員最初發(fā)現(xiàn) "typedef typename" 并列不太和諧,但它是涉及 nested dependent type names(嵌套依賴類型名)規(guī)則的一個(gè)合理的附帶結(jié)果。你會相當(dāng)快地習(xí)慣它。你畢竟有著強(qiáng)大的動機(jī)。你輸入 typename std::iterator_traits<IterT>::value_type 需要多少時(shí)間?

              作為結(jié)束語,我應(yīng)該提及編譯器與編譯器之間對圍繞 typename 的規(guī)則的執(zhí)行情況的不同。一些編譯器接受必需 typename 時(shí)它卻缺失的代碼;一些編譯器接受不許 typename 時(shí)它卻存在的代碼;還有少數(shù)的(通常是老舊的)會拒絕 typename 出現(xiàn)在它必需出現(xiàn)的地方。這就意味著 typename 和 nested dependent type names(嵌套依賴類型名)的交互作用會導(dǎo)致一些輕微的可移植性問題。

              Things to Remember

              ·在聲明 template parameters(模板參數(shù))時(shí),class 和 typename 是可互換的。

              ·用 typename 去標(biāo)識 nested dependent type names(嵌套依賴類型名),在 base class lists(基類列表)中或在一個(gè) member initialization list(成員初始化列表)中作為一個(gè) base class identifier(基類標(biāo)識符)時(shí)除外
            posted @ 2011-06-16 10:29 IT菜鳥 閱讀(107) | 評論 (0)編輯 收藏

            上層涉及到網(wǎng)絡(luò)消息時(shí),多線程的問題需要時(shí)時(shí)注意。OnRecvOnClose等消息的調(diào)用是在網(wǎng)絡(luò)線程中,而不是邏輯線程;如果需要在處理網(wǎng)絡(luò)消息時(shí)進(jìn)行邏輯操作,就一定要對多個(gè)線程都涉及到的變量加鎖。在邏輯復(fù)雜的環(huán)境(如邏輯服務(wù)器),把所有變量加鎖是不現(xiàn)實(shí)的,較簡單的一種解決方法是把網(wǎng)絡(luò)消息緩存起來,然后在邏輯線程的定時(shí)更新函數(shù)里處理這些緩存的消息。這樣,需要加鎖的只有這個(gè)緩存
            (待續(xù))
            posted @ 2011-04-18 09:53 IT菜鳥 閱讀(176) | 評論 (0)編輯 收藏

            新公司沒有WIKI,只有項(xiàng)目管理的redmine,所以想記錄點(diǎn)東西還比較麻煩,所以我決定在自己的機(jī)器上配置一下PHP的環(huán)境,裝上WORDPRESS,充當(dāng)WIKI用。而且導(dǎo)入導(dǎo)出也很方便,省掉了因?yàn)榫W(wǎng)絡(luò)不好寫blog的窩火和鬧心。

            1.apache安裝,沒啥說的 一路NEXT就可以了。
            2..php安裝,選擇版本的時(shí)候要注意下
            VC6 版本是使用 Visual Studio 6 編譯器編譯的,如果你是在windows下使用Apache+PHP的,請選擇VC6版本
            VC9 版本是使用 Visual Studio 2008 編譯器編譯的,如果你是在windows下使用IIS+PHP的,請選擇VC9版本
            所以選擇VC6的版本

            3.關(guān)鍵是兩個(gè)配置php.ini 和httpd.conf

            httpd.conf
            1.DocumentRoot(網(wǎng)站的根目錄)改成自己的,注意 "\"要改成 "/"
            2.DirectoryIndex(目錄索引) 添加index.php
            3.LoadModule php5_module G:/WEB/php/php5apache2_2.dll
               PHPIniDir "G:/WEB/php"
            4.AddType application/x-httpd-php .php AddType application/x-httpd-php .html

            php.ini
            1.extension:mysql前面的分號去掉
            2.d:/php d:/php/ext 目錄添加到環(huán)境變量里

            MySql如果之前有裝過的話,可能會出現(xiàn)問題cannot create windows service for mysql.error:0
            這樣只需要刪除MYSQL服務(wù)
            cmd下:執(zhí)行 sc delete mysql
            也可以把MySql的服務(wù)名該一下也OK
            posted @ 2011-04-09 13:20 IT菜鳥 閱讀(149) | 評論 (0)編輯 收藏

             http://blog.163.com/liuyuelin007@126/blog/static/213387692007411151568/

            http://blog.csdn.net/lychee007/archive/2009/05/31/4227419.aspx

            http://social.microsoft.com/Forums/es-ES/visualcpluszhchs/thread/ff6ddac2-a69d-4c02-ad20-d73cb4335c24

            http://hi.baidu.com/237rxd/blog/item/35a51efa18e098859e5146b9.html

            http://topic.csdn.net/t/20050712/20/4140158.html
            posted @ 2011-03-20 18:17 IT菜鳥 閱讀(420) | 評論 (0)編輯 收藏

                 摘要: 看到首頁上有人寫,自己也寫了一個(gè)名字起錯(cuò)了,其實(shí)寫個(gè)stack更合適 //!Node information//!struct Node{    int serialNumber;    int flag;    struct ...  閱讀全文
            posted @ 2011-03-16 10:58 IT菜鳥 閱讀(376) | 評論 (1)編輯 收藏

            不少筆試題都把這三個(gè)函數(shù)放一起比較,其實(shí)他們?nèi)齻€(gè)沒啥可比性,就是三個(gè)不同的函數(shù)而已

            Memset 用來對一段內(nèi)存空間全部設(shè)置為某個(gè)字符,一般用在對定義的字符串進(jìn)行初始化為‘ ’‘\0’

            主要應(yīng)用是初始化某個(gè)內(nèi)存空間

            :char a[100];memset(a, '\0', sizeof(a));

            memset可以方便的清空一個(gè)結(jié)構(gòu)類型的變量或數(shù)組。

            如:

            struct sample_struct
            {
             char   csName[16];
             int    iSeq;
             int    iType;
            };

            對于變量
            struct sample_strcut  stTest;

            一般情況下,清空stTest的方法:

            stTest.csName[0]='\0';
            stTest.iSeq=0;
            stTest.iType=0;

            memset就非常方便:
            memset(&stTest,0,sizeof(struct sample_struct));

            如果是數(shù)組:

             struct sample_struct   TEST[10];

            memset(TEST,0,sizeof(struct sample_struct)*10);

            memcpy 用來做內(nèi)存拷貝,你可以拿它拷貝任何數(shù)據(jù)類型的對象,可以指定拷貝的數(shù)據(jù)長度。

            memcpy是用于copy源空間的數(shù)據(jù)到目的空間中
            例:
            char a[100],b[50]; memcpy(b, a, sizeof(b));注意如用sizeof(a),會造成b的內(nèi)存地址溢出。

            Strcpy   就只能拷貝字符串了,它遇到'\0'就結(jié)束拷貝。

            例:char a[100],b[50];strcpy(a,b);如用strcpy(b,a),要注意a中的字符串長度(第一個(gè)‘\0’之前)是否超過50位,如超過,則會造成b的內(nèi)存地址溢出。


            strcpy用于字符串copy,遇到‘\0’,將結(jié)束

            posted @ 2011-03-15 08:06 IT菜鳥 閱讀(343) | 評論 (0)編輯 收藏

            僅列出標(biāo)題
            共7頁: 1 2 3 4 5 6 7 
            久久91精品国产91久久户| 精品永久久福利一区二区| 久久精品亚洲福利| 国产亚州精品女人久久久久久| 精品免费久久久久国产一区| 久久国产成人午夜AV影院| 久久乐国产综合亚洲精品| 少妇高潮惨叫久久久久久| 伊人久久免费视频| 狠狠色丁香久久婷婷综合_中| 精品国产福利久久久| 香蕉久久影院| 亚洲精品高清久久| 亚洲国产精品高清久久久| 91精品国产高清久久久久久国产嫩草 | 久久精品国产亚洲7777| 亚洲中文久久精品无码ww16| 久久精品成人免费观看97| 日韩久久久久久中文人妻| 97久久精品人人做人人爽| 日韩精品无码久久久久久| 2021国产精品久久精品| 精品久久久久久无码免费| 好属妞这里只有精品久久| 久久精品国产99国产精品亚洲| 国产L精品国产亚洲区久久| 精品久久8x国产免费观看| 一级做a爰片久久毛片看看| 久久人搡人人玩人妻精品首页| 国产精品久久久久久影院| 中文字幕人妻色偷偷久久| 久久伊人五月丁香狠狠色| 亚洲日韩欧美一区久久久久我| 国产成人精品久久| 国产精品美女久久久久AV福利| 久久精品国产半推半就| 国产一久久香蕉国产线看观看| 蜜臀av性久久久久蜜臀aⅴ麻豆 | 久久精品国产日本波多野结衣| 国产福利电影一区二区三区久久久久成人精品综合 | 久久精品国产99国产精品 |