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

            Onway

            我是一只菜菜菜菜鳥...
            posts - 61, comments - 56, trackbacks - 0, articles - 34

            熟悉C++標(biāo)準(zhǔn)庫(轉(zhuǎn))

            Posted on 2010-11-03 09:15 Onway 閱讀(337) 評論(0)  編輯 收藏 引用 所屬分類: 轉(zhuǎn)載

            C++標(biāo)準(zhǔn)庫非常大。在C++標(biāo)準(zhǔn)中,關(guān)于標(biāo)準(zhǔn)庫的規(guī)格說明占了密密麻麻300多頁,這還不包括標(biāo)準(zhǔn)C庫,后者只是 "作為參考"包含在C++庫中。

             

            當(dāng)然,并非總是越大越好,但在現(xiàn)在的情況下,確實越大越好,因為大的庫會包含大量的功能。標(biāo)準(zhǔn)庫中的功能越多,開發(fā)自己的應(yīng)用程序時能借助的功能就越多。C++庫并非提供了一切(沒有提供并發(fā)和圖形用戶接口的支持),但確實提供了很多。幾乎任何事都可以求助于它。

             

            因為標(biāo)準(zhǔn)庫中東西如此之多,你所選擇的類名或函數(shù)名就很有可能和標(biāo)準(zhǔn)庫中的某個名字相同。為了避免這種情況所造成的名字沖突,實際上標(biāo)準(zhǔn)庫中的一切都被放在名字空間std中。但這帶來了一個新問題。無數(shù)現(xiàn)有的C++代碼都依賴于使用了多年的偽標(biāo)準(zhǔn)庫中的功能,例如,聲明在<iostream.h>,<complex.h>,<limits.h>等頭文件中的功能。現(xiàn)有軟件沒有針對使用名字空間而進(jìn)行設(shè)計,如果用std來包裝標(biāo)準(zhǔn)庫導(dǎo)致現(xiàn)有代碼不能用,將是一種可恥行為。

             

            懾于被激怒的程序員會產(chǎn)生的破壞力,標(biāo)準(zhǔn)委員會決定為包裝了std的那部分標(biāo)準(zhǔn)庫構(gòu)件創(chuàng)建新的頭文件名。生成新頭文件的方法僅僅是將現(xiàn)有C++頭文件名中的 .h 去掉,方法本身不重要,正如最后產(chǎn)生的結(jié)果不一致也并不重要一樣。所以<iostream.h>變成了<iostream>,<complex.h>變成了<complex>,等等。對于C頭文件,采用同樣的方法,但在每個名字前還要添加一個c。所以C的<string.h>變成了<cstring>,<stdio.h>變成了<cstdio>,等等。最后一點是,舊的C++頭文件是官方所反對使用的(即明確列出不再支持),但舊的C頭文件則沒有(以保持對C的兼容性)。實際上,編譯器制造商不會停止對客戶現(xiàn)有軟件提供支持,所以可以預(yù)計,舊的C++頭文件在未來幾年內(nèi)還是會被支持。

            所以,實際來說,下面是C++頭文件的現(xiàn)狀:

             

            · 舊的C++頭文件名如<iostream.h>將會繼續(xù)被支持,盡管它們不在官方標(biāo)準(zhǔn)中。這些頭文件的內(nèi)容不在名字空間std中。

            · 新的C++頭文件如<iostream>包含的基本功能和對應(yīng)的舊頭文件相同,但頭文件的內(nèi)容在名字空間std中。(在標(biāo)準(zhǔn)化的過程中,庫中有些部分的細(xì)節(jié)被修改了,所以舊頭文件和新頭文件中的實體不一定完全對應(yīng)。)

            · 標(biāo)準(zhǔn)C頭文件如<stdio.h>繼續(xù)被支持。頭文件的內(nèi)容不在std中。

            · 具有C庫功能的新C++頭文件具有如<cstdio>這樣的名字。它們提供的內(nèi)容和相應(yīng)的舊C頭文件相同,只是內(nèi)容在std中。

             

            所有這些初看有點怪,但不難習(xí)慣它。最大的挑戰(zhàn)是把字符串頭文件理清楚:<string.h>是舊的C頭文件,對應(yīng)的是基于char*的字符串處理函數(shù);<string>是包裝了std的C++頭文件,對應(yīng)的是新的string類;<cstring>是對應(yīng)于舊C頭文件的std版本。如果能掌握這些,其余的也就容易了。

             

            關(guān)于標(biāo)準(zhǔn)庫,需要知道的第二點是,庫中的一切幾乎都是模板。iostream幫助你操作字符流,但什么是字符?是char嗎?是wchar_t?是Unicode字符?一些其它的多字節(jié)字符?沒有明顯正確的答案,所以標(biāo)準(zhǔn)庫讓你去選。所有的流類(stream class)實際上是類模板,在實例化流類的時候指定字符類型。例如,標(biāo)準(zhǔn)庫將cout類型定義為ostream,但ostream實際上是一個basic_ostream<char>類型定義(typedef )。

             

            類似的考慮適用于標(biāo)準(zhǔn)庫中其它大部分類。string不是類,它是類模板:類型參數(shù)限定了每個string類中的字符類型。complex不是類,它是類模板:類型參數(shù)限定了每個complex類中實數(shù)部分和虛數(shù)部分的類型。vector不是類,它是類模板。如此不停地進(jìn)行下去。

            在標(biāo)準(zhǔn)庫中無法避開模板,但如果只是習(xí)慣于和char類型的流和字符串打交道,通常可以忽略它們。這是因為,對這些組件的char實例,標(biāo)準(zhǔn)庫都為它們定義了typedef,這樣就可以在編程時繼續(xù)使用cin,cout,cerr等對象,以及istream,ostream,string等類型,不必?fù)?dān)心cin的真實類型是basic_istream<char>以及string的真實類型是basic_string<char>。

             

            標(biāo)準(zhǔn)庫中很多組件的模板化和上面所建議的大不相同。再看看那個概念上似乎很直觀的string。當(dāng)然,可以基于 "它所包含的字符類型" 確定它的參數(shù),但不同的字符集在細(xì)節(jié)上有不同,例如,特殊的文件結(jié)束字符,拷貝它們的數(shù)組的最有效方式,等等。這些特征在標(biāo)準(zhǔn)中被稱為traits,它們在string實例中通過另外一個模板參數(shù)指定。此外,string對象要執(zhí)行動態(tài)內(nèi)存分配和釋放,但完成這一任務(wù)有很多不同的方法。哪一個最好?選擇:string模板有一個Allocator參數(shù),Allocator類型的對象被用來分配和釋放string對象所使用的內(nèi)存。

             

            這里有一個basic_string模板的完整聲明,以及建立在它之上的string類型定義(typedef);可以在<string>頭文件中找到它(或與之相當(dāng)?shù)氖裁礀|西):

             

            namespace std {

               template<class charT,
                        class traits = char_traits<charT>,
                        class Allocator = allocator<charT> >
                  class basic_string;

               typedef basic_string<char> string;

            }

             

            注意,basic_string的traits和Allocator參數(shù)有缺省值。這在標(biāo)準(zhǔn)庫中是很典型的做法。它為使用者提供了靈活性,但對于這種靈活性所帶來的復(fù)雜性,那些只想做 "正常" 操作的"典型" 用戶卻又可以避開。換句話說,如果只想使用象C字符串那樣的字符串對象,就可以使用string對象,而不用在意實際上是在用basic_string<char, char_traits<char>, allocator<char> >類型的對象。

             

            通常可以這么做,但有時還是得稍稍看看底層。例如,聲明一個類而不提供定義具有優(yōu)點;它還指出,下面是一種聲明string類型的錯誤方法:

            class string;                    // 會通過編譯,

             

            先不要考慮名字空間,這里真正的問題在于:string不是一個類,而是一個typedef。如果可以通過下面的方法解決問題就太好了:

            typedef basic_string<char> string;

             

            但這又不能通過編譯。"所說的basic_string是什么東西?" 編譯器會奇怪 ---- 當(dāng)然,它可能會用不同的語句來問你。所以,為了聲明string,首先得聲明它所依賴的所有模板。如果可以這么做的話,就會象下面這樣:

             

            template<class charT> struct char_traits;

            template<class T> class allocator;

            template<class charT, class traits = char_traits<charT>,
            class Allocator = allocator<charT> >
            class basic_string;

            typedef basic_string<char> string;

             

            然而,你不能聲明string。至少不應(yīng)該。這是因為,標(biāo)準(zhǔn)庫的實現(xiàn)者聲明的stirng(或std名字空間中任何其它東西)可以和標(biāo)準(zhǔn)中所指定的有所不同,只要最終提供的行為符合標(biāo)準(zhǔn)就行。例如,basic_string的實現(xiàn)可以增加第四個模板參數(shù),但這個參數(shù)的缺省值所產(chǎn)生的代碼的行為要和標(biāo)準(zhǔn)中所說的原始的basic_string一致。那到底該怎么辦?不要手工聲明string(或標(biāo)準(zhǔn)庫中其它任何部分)。相反,只用包含一個適當(dāng)?shù)念^文件,如<string>。

             

            有了頭文件和模板的這些知識,現(xiàn)在可以看看標(biāo)準(zhǔn)C++庫中有哪些主要組件:

            · 標(biāo)準(zhǔn)C庫。它還在,還可以用它。雖然有些地方有點小的修修補(bǔ)補(bǔ),但無論怎么說,還是那個用了多年的C庫。

             

            · Iostream。和 "傳統(tǒng)" Iostream的實現(xiàn)相比,它已經(jīng)被模板化了,繼承層次結(jié)構(gòu)也做了修改,增強(qiáng)了拋出異常的能力,可以支持string(通過stringstream類)和國際化(通過locales)。當(dāng)然,你期望Iostream庫所具有的東西幾乎全都繼續(xù)存在。也就是說,它還是支持流緩沖區(qū),格式化標(biāo)識符,操作子和文件,還有cin,cout,cerr和clog對象。這意味著可以把string和文件當(dāng)做流,還可以對流的行為進(jìn)行更廣泛的控制,包括緩沖和格式化。

             

            · String。string對象在大多數(shù)應(yīng)用中被用來消除對char*指針的使用。它們支持你所期望的那些操作(例如,字符串連接,通過operator[]對單個字符進(jìn)行常量時間級的訪問,等等),它們可以轉(zhuǎn)換成char*,以保持和現(xiàn)有代碼的兼容性,它們還自動處理內(nèi)存管理。一些string的實現(xiàn)采用了引用計數(shù),這會帶來比基于char*的字符串更佳的性能(時間和空間上)。

             

            · 容器。標(biāo)準(zhǔn)庫提供了高效的容器實現(xiàn):vector(就象動態(tài)可擴(kuò)充的數(shù)組),list(雙鏈表),queue, stack,deque,map,set和bitset。但多少可以作為補(bǔ)償?shù)囊稽c是, string是容器。這很重要,因為它意味著對容器所做的任何操作對string也適用。

            標(biāo)準(zhǔn)庫規(guī)定了每個類的接口,而且每條接口規(guī)范中的一部分是一套性能保證。所以,舉例來說,無論vector是如何實現(xiàn)的,僅僅提供對它的元素的訪問是不夠的,還必須提供 "常量時間" 內(nèi)的訪問。如果不這樣,就不是一個有效的vector實現(xiàn)。

            很多C++程序中,動態(tài)分配字符串和數(shù)組導(dǎo)致大量使用new和delete,new/delete錯誤 ---- 尤其是沒有delete掉new出來的內(nèi)存而導(dǎo)致的泄漏 ---- 時常發(fā)生。如果使用string和vector對象(二者都執(zhí)行自身的內(nèi)存管理)而不使用char*和動態(tài)分配的數(shù)組的指針,很多new和delete就可以免于使用,使用它們所帶來的問題也會隨之消失。

             

            · 算法。標(biāo)準(zhǔn)庫就提供了大量簡易的方法(即,預(yù)定義函數(shù),官方稱為算法(algorithm) ---- 實際上是函數(shù)模板),其中的大多數(shù)適用于庫中所有的容器 ---- 以及內(nèi)建數(shù)組(built-in arrays)。

            算法將容器的內(nèi)容當(dāng)作序列(sequence),每個算法可以應(yīng)用于一個容器中所有值所對應(yīng)的序列,或者一個子序列(subsequence)。標(biāo)準(zhǔn)算法有for_each(為序列中的每個元素調(diào)用某個函數(shù)),find(在序列中查找包含某個值的第一個位置,count_if(計算序列中使得某個判定為真的所有元素的數(shù)量),equal(確定兩個序列包含的元素的值是否完全相同),search(在一個序列中找出某個子序列的起始位置),copy(拷貝一個序列到另一個),unique(在序列中刪除重復(fù)值),rotate(旋轉(zhuǎn)序列中的值),sort(對序列中的值排序)。注意這里只是抽取了所有算法中的幾個;標(biāo)準(zhǔn)庫中還包括其它很多算法。

            和容器操作一樣,算法也有性能保證。例如,stable_sort算法執(zhí)行時要求不超過0比較級(N log N) 。(stable_sort提供的性能必須和最高效的通用排序算法在同一個級別。)

             

            · 對國際化的支持。不同的文化以不同的方式行事。和C庫一樣,C++庫提供了很多特性有助于開發(fā)出國際化的軟件。但雖然從概念上來說和C類似,其實C++的方法還是有所不同。例如,C++為支持國際化廣泛使用了模板,還利用了繼承和虛函數(shù),這些一定不會讓你感到奇怪。

            支持國際化最主要的構(gòu)件是facets和locales。facets描述的是對一種文化要處理哪些特性,包括排序規(guī)則(即,某地區(qū)字符集中的字符應(yīng)該如何排序),日期和時間應(yīng)該如何表示,數(shù)字和貨幣值應(yīng)該如何表示,怎樣將信息標(biāo)識符映射成(自然的)明確的語言信息,等等。locales將多組facets捆綁在一起。例如,一個關(guān)于美國的locale將包括很多facets,描述如何對美國英語字符串排序,如何以適合美國人的方式讀寫日期和時間,讀寫貨幣和數(shù)字值,等等。而對于一個關(guān)于法國的locales來說,它描述的是怎么以法國人所習(xí)慣的方式完成這些任務(wù)。C++允許單個程序中同時存在多個locales,所以一個應(yīng)用中的不同部分可能采用的是不同的規(guī)范。

             

            · 對數(shù)字處理的支持。C++庫為復(fù)數(shù)類(實數(shù)和虛數(shù)部分的精度可以是float,double或long double)和專門針對數(shù)值編程而設(shè)計的特殊數(shù)組提供了模板。例如,valarray類型的對象可用來保存可以任意混疊(aliasing)的元素。這使得編譯器可以更充分地進(jìn)行優(yōu)化,尤其是對矢量計算機(jī)來說。標(biāo)準(zhǔn)庫還對兩種不同類型的數(shù)組片提供了支持,并提供了算法計算內(nèi)積(inner product),部分和(partial sum),臨差(adjacent difference)等。

             

            · 診斷支持。標(biāo)準(zhǔn)庫支持三種報錯方式:C的斷言,錯誤號,例外。為了有助于為例外類型提供某種結(jié)構(gòu),標(biāo)準(zhǔn)庫定義了下面的例外類(exception class)層次結(jié)構(gòu):

                                                                |---domain_error
                                 |----- logic_error<---- |---invalid_argument
                                 |                               |---length_error
                                 |                               |---out_of_range
            exception<--|
                                 |                                |--- range_error
                                 |-----runtime_error<--|---underflow_error
                                                                 |---overflow_error

            logic_error(或它的子類)類型的例外表示的是軟件中的邏輯錯誤。理論上來說,這樣的錯誤可以通過更仔細(xì)的程序設(shè)計來防止。runtime_error(或它的子類)類型的例外表示的是只有在運(yùn)行時才能發(fā)現(xiàn)的錯誤。

            可以就這樣使用它們,可以通過繼承它們來創(chuàng)建自己的例外類,或者可以不去管它。沒有人強(qiáng)迫你使用它。

            上面列出的內(nèi)容并沒有涵蓋標(biāo)準(zhǔn)庫中的一切。

             

            標(biāo)準(zhǔn)庫中容器和算法這部分一般稱為標(biāo)準(zhǔn)模板庫。STL中實際上還有第三個構(gòu)件 ---- 迭代子(Iterator)。迭代子是指針?biāo)频膶ο螅孲TL算法和容器共同工作。

             

            STL是標(biāo)準(zhǔn)庫中最具創(chuàng)新的部分,這并不是因為它提供了容器和算法(雖然它們非常有用),而是因為它的體系結(jié)構(gòu)。簡單來說,它的體系結(jié)構(gòu)具有擴(kuò)展性:可以對STL進(jìn)行添加。當(dāng)然,標(biāo)準(zhǔn)庫中的組件本身是固定的,但如果遵循STL構(gòu)建的規(guī)范,可以寫出自己的容器,算法和迭代子,使它們可以和標(biāo)準(zhǔn)STL組件一起工作,就象標(biāo)準(zhǔn)組件自身之間相互工作一樣。還可以利用別人所寫的符合STL規(guī)范的容器,算法和迭代子,就象別人利用你的一樣。使得STL具有創(chuàng)新意義的原因在于它實際上不是軟件,而是一套規(guī)范(convention)。標(biāo)準(zhǔn)庫中的STL組件只是具體體現(xiàn)了遵循這種規(guī)范所能帶來的好處。

             

            通過使用標(biāo)準(zhǔn)庫中的組件,通常可以避免從頭到尾來設(shè)計自己的IO流,string,容器,國際化,數(shù)值數(shù)據(jù)結(jié)構(gòu)以及診斷等機(jī)制。這就有更多的時間和精力去關(guān)注軟件開發(fā)中真正重要的部分:實現(xiàn)軟件的其他功能。


            轉(zhuǎn)自:http://hi.baidu.com/why0813/blog/item/850ea46eecf658db80cb4a6a.html

            麻豆精品久久久一区二区| 久久天天躁夜夜躁狠狠| 伊人久久大香线蕉精品| 久久久久亚洲精品男人的天堂| 无码精品久久一区二区三区| 久久综合88熟人妻| 青青久久精品国产免费看| 久久精品国产99久久久| 香港aa三级久久三级老师2021国产三级精品三级在 | 2019久久久高清456| 91久久精品91久久性色| 亚洲人成网站999久久久综合 | 久久最近最新中文字幕大全| 久久人人爽人人爽人人片AV东京热| 久久国产成人精品麻豆 | 97精品国产97久久久久久免费 | 亚洲国产成人久久综合碰| 国产美女久久精品香蕉69| 7777精品伊人久久久大香线蕉| 91精品国产高清久久久久久91| 精品久久久久久久久免费影院| 99久久国产热无码精品免费久久久久| 国产A级毛片久久久精品毛片| 日韩欧美亚洲国产精品字幕久久久| A狠狠久久蜜臀婷色中文网| 亚洲国产精品久久久天堂| 欧美日韩精品久久免费| 亚洲国产成人精品久久久国产成人一区二区三区综 | 精品综合久久久久久888蜜芽| 狠狠色丁香久久婷婷综合蜜芽五月 | 日本久久久久亚洲中字幕| 久久精品国产免费观看| 欧美精品乱码99久久蜜桃| 国产精品成人久久久| 人妻无码αv中文字幕久久琪琪布| 亚洲国产精品无码久久久久久曰 | 无码人妻久久一区二区三区免费| 中文字幕无码免费久久| 日日躁夜夜躁狠狠久久AV| 久久精品天天中文字幕人妻| 国产亚洲欧美精品久久久|