• <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++標準庫(轉)

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

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

             

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

             

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

             

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

            所以,實際來說,下面是C++頭文件的現狀:

             

            · 舊的C++頭文件名如<iostream.h>將會繼續被支持,盡管它們不在官方標準中。這些頭文件的內容不在名字空間std中。

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

            · 標準C頭文件如<stdio.h>繼續被支持。頭文件的內容不在std中。

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

             

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

             

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

             

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

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

             

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

             

            這里有一個basic_string模板的完整聲明,以及建立在它之上的string類型定義(typedef);可以在<string>頭文件中找到它(或與之相當的什么東西):

             

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

             

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

            class string;                    // 會通過編譯,

             

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

            typedef basic_string<char> string;

             

            但這又不能通過編譯。"所說的basic_string是什么東西?" 編譯器會奇怪 ---- 當然,它可能會用不同的語句來問你。所以,為了聲明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。至少不應該。這是因為,標準庫的實現者聲明的stirng(或std名字空間中任何其它東西)可以和標準中所指定的有所不同,只要最終提供的行為符合標準就行。例如,basic_string的實現可以增加第四個模板參數,但這個參數的缺省值所產生的代碼的行為要和標準中所說的原始的basic_string一致。那到底該怎么辦?不要手工聲明string(或標準庫中其它任何部分)。相反,只用包含一個適當的頭文件,如<string>。

             

            有了頭文件和模板的這些知識,現在可以看看標準C++庫中有哪些主要組件:

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

             

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

             

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

             

            · 容器。標準庫提供了高效的容器實現:vector(就象動態可擴充的數組),list(雙鏈表),queue, stack,deque,map,set和bitset。但多少可以作為補償的一點是, string是容器。這很重要,因為它意味著對容器所做的任何操作對string也適用。

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

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

             

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

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

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

             

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

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

             

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

             

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

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

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

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

            上面列出的內容并沒有涵蓋標準庫中的一切。

             

            標準庫中容器和算法這部分一般稱為標準模板庫。STL中實際上還有第三個構件 ---- 迭代子(Iterator)。迭代子是指針似的對象,它讓STL算法和容器共同工作。

             

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

             

            通過使用標準庫中的組件,通常可以避免從頭到尾來設計自己的IO流,string,容器,國際化,數值數據結構以及診斷等機制。這就有更多的時間和精力去關注軟件開發中真正重要的部分:實現軟件的其他功能。


            轉自:http://hi.baidu.com/why0813/blog/item/850ea46eecf658db80cb4a6a.html

            一本久久综合亚洲鲁鲁五月天亚洲欧美一区二区| 热re99久久精品国99热| 99久久99久久精品国产片| 国内精品免费久久影院| 伊人久久综合无码成人网| 97久久超碰国产精品2021| 久久国产综合精品五月天| 亚洲色大成网站WWW久久九九| 久久精品国产半推半就| 久久久久久久91精品免费观看| 久久天天躁狠狠躁夜夜网站| 91亚洲国产成人久久精品| 无码国内精品久久人妻蜜桃| 国产日韩久久免费影院| 777米奇久久最新地址| 久久久久se色偷偷亚洲精品av| 久久精品无码一区二区app| 91久久精一区二区三区大全| 久久99这里只有精品国产| 久久精品国产99久久香蕉| 久久99精品久久只有精品| 久久经典免费视频| 久久精品综合一区二区三区| 久久综合狠狠综合久久激情 | 国产福利电影一区二区三区久久老子无码午夜伦不 | 久久这里只有精品首页| 国产成人精品久久亚洲高清不卡| 精品一二三区久久aaa片| 久久亚洲国产成人精品无码区| 久久被窝电影亚洲爽爽爽| 久久精品国产精品亚洲毛片| 久久国语露脸国产精品电影| 一本久道久久综合狠狠躁AV| 久久无码国产| 久久久久亚洲AV无码专区首JN| 美女久久久久久| 色妞色综合久久夜夜| 亚洲中文字幕无码一久久区| 久久人人爽人人爽人人爽| 婷婷伊人久久大香线蕉AV| 久久精品九九亚洲精品|