Effective C++ 49,50

49.熟悉標準庫。

C++標準庫很大。

首先標準庫中函數很多,爲了避免名字衝突,使用命名空間std。而之前的庫函數都存放於< .h>中,現在成爲僞標準庫。而不能直接將這些頭文件全部直接添加命名空間,標準委員會只能重新創建了不帶.h的頭文件。對於C中頭文件採用同樣的方法,但是每個名字前添加一個c,如C中的<string.h>變成了<cstring>。舊的c++頭文件是官方反對使用的,但舊的c頭文件不是,爲了保持對C的兼容性。如 <string.h>是舊的C頭文件,對應的是基於char*的字符串處理函數,<string>是包含了std的C++頭文件,對應的是新的string類,而<cstring>是C頭文件的std版本,但這裏沒有string類的舊c++版本,因爲官方不推薦這樣做。

第二,庫中幾乎都是模版。如iostream,操作字符流,流類實際就是類模版,在實例化流類的時候指定字符類型。即使是string,其實也是一個模版,類型參數限定了每個string類中的字符類型。string的類型聲明是:

typedef basic_string<char, char_traits<char>, allocator<char> >
	string;

這裏的字符類型與之前iostream中的字符類型是一個意思,它不是指char,指的是一個流中的字符,這裏字符類型確定其參數,字符類型指的是字符集,因爲不同的字符集在實現的細節上不同,如特殊的文件結束字符,拷貝他們的數組的最有效方式等,這些特徵在標準中被稱爲traits。然後還有string對象執行動態內存分配的方法,使用一個Allocator參數,而Allocator類型的對象被用來分配和釋放string對象的內存,其是一個內存管理器。不要手動的聲明標準庫中的任何部分。

Iostream,和傳統的Iostream相比,它已經被模版化,繼承層次結構也進行了修改,增加了拋出異常的能力,支持string(通過stringstream)和國際化(通過locales)。新的Iostream可以將string和文件當作流,還可以對流的行爲做更廣泛的控制,包括緩存和初始化。

容器,標準庫中提供了一下的高效實現,vector,list,queue,stack,deque,map,set和bitset。string是容器,對容器的任何操作都適用於string。標準庫的實現是高效的。使用容器可以消除動態分配內存造成的內存泄漏。

算法,標準庫中提供了大量的簡易方法,稱爲algorithm,實際爲函數模版,其中大多數適用於庫中所有容器以及內建數組。算法將容器的內容作爲序列,每個算法可以應用與一個容器中所有值對應的一個序列,或者一個子序列。標準算法有,for_each 爲序列中的每個元素調用某個函數, find 在序列中查找包含某個值的第一個位置, count_if 計算序列中滿足某個判定爲真的元素的數量,equal 判斷兩個序列包含的元素的值是否完全相等,search 在一個序列中找出某個子序列的起始位置,copy 拷貝一個序列到另一個, unique 在序列中刪除重複值, rotate 旋轉序列中的值,sort 對序列中的值排序,等等。和容器操作一樣,算法也有性能保證。

對國際化的支持。提供有助於開發出國際化軟件的特性。支持國際化的最主要的構件是facets 和 locales 。facets描述的是對一種文化要處理哪些特性,包括排序規則(即某些地區字符集中的字符應該如何排序),日期和時間應該如何表示,數字和貨幣值應該如何表示,怎樣將信息表示符映射成明確的語言信息,等等。locales 將多組facets捆綁在一起,facets是指前面說到的那些特性中的一個,而locales 表示多個facets組成的一個對於某個國家的規則,若一個locales表示美國人是如何解決前面幾個問題的。

對於數字處理的支持。C++庫中爲複數類和專門針對數值編程而設計的特殊數組提供了模版。如valarray 類型的對象可以用來保存可以任意混疊的元素,

診斷支持,標準庫支持三種報錯方式:C的斷言,錯誤號,例外 exception 。例外先派生出 logic_error 和 runtime_error ,然後再有這兩個類派生出具體的錯誤類型,logic_error 表示軟件中的邏輯錯誤,理論上可以通過更仔細的程序設計來防止。runtime_error 類型的例外爲運行時才能發現的錯誤。

標準庫中的容器和算法這部分一般被稱爲標準模版庫 STL 。STL是標準庫中最具創新的部分,它的體系結構具有擴展性,按照STL中的規範,可以進行很多擴展。


50.提高對C++的認識。

C++設計時的首要目標:與C的兼容性,效率,和傳統開發工具及環境的兼容性,解決真實問題的可應用性(即面向對象)。

以上目標闡明瞭C++語言中大量的實現細節。如,爲什麼隱式生成的拷貝構造函數和賦值運算符要像現在這樣工作,尤其是指針產生的淺拷貝問題?因爲這是C對struct的拷貝和賦值的方式,要與C兼容。爲什麼析構函數不自動聲明爲virtual,爲什麼實現細節必須出現在類的定義中?因爲不這樣做會帶來性能上的損失,效率很重要。爲什麼C++不能檢測非局部靜態對象間的初始化依賴關係?因爲C++支持單獨編譯(即,分開編譯源模塊,然後將多個目標文件鏈接起來,形成可執行程序),依賴現有的鏈接器,不會程序數據打交道,所以c++編譯器幾乎不可能知道整個程序的一切情況。爲什麼C++不讓程序員從一些繁雜事務如內存管理和低級指針操作中解脫出來?因爲一些程序員需要這些處理能力,一個真正的程序員的需要自關重要。




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章