C++ basic_string(字串類別範本)詳解

2020-07-16 10:04:42

"字元" 本身是個有趣的抽象概念。例如,在紙上或者螢幕上,字元 "C" 僅僅是一段曲線而已。在計算機中,用一個 8 Byte 儲存該字元,並賦值 67;字元 "C" 還是拉丁字母的第三個字母;在化學專業,字元 "C" 是原子碳的縮寫形式;在計算機學科中,字元 "C" 又被用來表示一種程式設計語言的名字。


目前,在計算機領域,字元集合是在字元與整數值之間的一種對映關係。

C++ 程式設計師通常假定能夠使用美國字元集(ASCII),但 C++ 允許程式設計師缺少某些字元的可能性。如果在程式開發過程中,原始碼含有 ASCII 裡所沒有的字元,這是比較麻煩的,許多語言(例如中文、丹麥文、法文、冰島文、日文)無法用 ASCII 中的字元正常寫出來,即使擴充到 16 位字元集,也無法將人類所知的所有字元放在同一字元集中。據說已經出現的 32 位字元集能儲存每一個字元,但因字元數量龐大,不便於使用,尚未得到推廣。

C++ 語言允許程式設計師使用任何字元集作為字串的字元,也允許程式設計師使用擴充字元集或可移植的數值編碼。從原則上講,字串能以任何(帶有正確的複製操作)型別作為其字元型別。標準字串類 string 要求其中的字元不能包含使用者自定義複製操作,有助於字串 I/O 的簡化與高效率。

字元型別的性質是由字元特徵類(char_traits)定義的。字元特徵類是下述模板的特例:

template <class Ch> struct char_traits { }

所有字元特徵類均定義在名稱空間 std 中,標準的字元特徵類由標頭檔案 <String> 給出。通用字串特徵類 char_traits 本身不具有任何屬性,只有針對特定字元型別的專門 char_traits 才具有屬性。

標準字串模板的範例類 basic_string 依賴於諸多型別和函數。若一個型別作為 basic_string 字元型別,必須提供支援上述功能的字元特徵類(char_traits)。

C++ 的字串模板範例化類 basic_string 中,還集合了大量的字串處理常式,與標準容器類似。該類別範本的宣告如下:
template <class Ch, class Tr = char_traits <Ch>, class A=allocator <Ch>> class std::basic_string
{
    public:
    ...
}
在上述模板宣告中,第一個引數(class Ch)是說明單個字元(Ch)所屬型別(class)。

第二個引數(class Tr = char_traits <Ch>)是特性類別,用以提供字串類別中的所有字元核心操作。該特性類別規定了“複製字元”或“比較字元”的做法;如果不指定該特性類別,系統會根據現有的字元型別採用預設的特性類別。

第三個引數帶有預設值(class A = allocator<Ch>),用以定義字串類別所採用的記憶體模式,通常設定為“預設記憶體模型 allocator”。該模板及其相關功能都定義在名稱空間 std 中,由標頭檔案 <string> 給出,其中包含了兩個定義型別,可以為最常用的串型別提供便於使用的名稱,即 C++ STL 提供了兩個 basic_string<> 範例化版本:

typedef basic_string <char> string;
typedef basic_string <wchar> wstring;

其中,wstring 類是為了便於使用寬字元集,例如 Unicode 或某些歐洲字元集。但所有字串型別均使用相同介面,其用法和問題是相同的。在本教學中,仍以 string 表示任何字串型別。

basic_string 和 vector 類似,而 basic_string 還提供典型的字串操作,例如子串檢索。basic_string 沒有提供一組完整的操作函數。通常 string 不能直接使用陣列或者 vector,為了更好地支援 string 的常見應用,程式設計師在實現過程中需要盡量減少複製。尤其對於較短的字串,不應使用自由儲存空間,但允許對較長的字串進行簡單修改。

basic_string<T> 沒有虛擬函式,這點和其他標準庫型別一致。當需要設計更複雜的文書處理類時,可考慮用它加以實現。

與其他標準容器相似,basic_string 提供了一組成員型別名,程式設計師能使用這些與串相關的型別。例如:

typedef Tr traits_type;
typedef typename Tr::char_type value_type
typedef A allocator_type
……

basic_string 除支援最簡單的 basic_string <char> 之外,還支援許多不同種類的字串,例如:

typedef basic_string <unsigned char> Ustring;
tyepdef basic_string <Jchar> Jstring; //日文字串

無論如何定義字串,模板 basic_string 的大量函數均可便捷地使用。模板 basic_string<Ch> 能夠存放集合 Ch 中的任何字元,特別是 string 中的 '0'。"字元型別" Ch 的行為必須像字元,但它不能包含使用者確定的複製建構函式、解構函式和複製賦值。

雖然字串類 string 包含了諸多的成員和函數,但個別功能沒能夠實現,例如正規表示式和較複雜的文字處理功能。

總體而言,string 類似的字串操作逐漸變得簡單了。程式設計師可以定義 string 型別的物件、string 類的過載操作符和成員函數,這使字串操作變得非常容易。