String (C++ 標準庫)

是 C++ 標準程式庫中的一個標頭檔案，定義了 C++ 標準中的字串的基本模板類 std::basic_string 及相關的模板類例項：

其中的 string 是以 char 作為模板引數的模板類例項，把字串的記憶體管理責任由 string 負責而不是由程式設計者負責，大大減輕了 C 語言風格的字串的麻煩。

std::basicstring 提供了大量的字串操作函式，如比較、連線、搜尋、替換、獲得子串等。並可與 C 語言風格字串雙向轉換。std::basicstring 屬於 C++ STL 容器類，使用者自定義的類也可以作為它的模板引數，因此也適用 C++ STL Algorithm 庫。

string 本質上是以字元作為元素的 vector 特化版本；不存在 0 字元結尾這個概念，能裝入 '\0' 這種資料。

std::basic_string 類模板

std::basicstring 類模板儲存且操縱類似 char 的物件的序列。該物件型別的性質由特性類模板 std::chartraits 的例項來提供，並作為 std::basic_string 的第二個模板引數。

C++11 標準規定：basicstring 的元素是連續儲存的。即對於 basicstring s，有：&(s.begin + n) == &s.begin + n，其中 n 屬於 0, s.size )。換句話說，指向 s0 的指標即為指向 CharT 陣列的首元素指標。C++11 已經禁止了寫入時複製（copy-on-write) 的實現，因為存在多執行緒安全問題。一般都採用了小字串最佳化（SSO）實現，如 Visual C++：

union _Bxty

{ //storage for small buffer or pointer to larger one

Elem BufBUFSIZE;

Elem *Ptr;

} _Bx;

sizetype Mysize; //current length of string

sizetype Myres; //current storage reserved for string

GCC 從版本 5 開始，std::string 不再採用 COW 策略。

C++17 標準規定，basic_string 是 AllocatorAwareContainer, SequenceContainer 與 ContiguousContainer。

1.1 模板引數

CharT 	- 	字元型別
Traits 	- 	字元的特性類
Allocator 	內部儲存的分配器類

1.2 成員型別

traits_type 	模板引數 Traits
valuetype 	即 Traits::chartype
allocator_type 模板引數 Allocator
sizetype 	即 Allocator::sizetype。C++11 改為 std::allocatortraits::sizetype
differencetype 即 Allocator::differencetype。C++11 改為 std::allocatortraits::differencetype
reference 	即 Allocator::reference。C++11 改為 value_type&
constreference 即 Allocator::constreference。C++11 改為 const value_type&
pointer 	即 Allocator::pointer。C++11 改為 std::allocator_traits::pointer
constpointer 	即 Allocator::constpointer。C++11 改為 std::allocatortraits::constpointer
iterator 	屬於 RandomAccessIterator
const_iterator 	屬於 Constant random access iterator
reverseiterator 	即 std::reverseiterator
constreverseiterator 	即 std::reverse_iterator

1.3 成員函式

下面列出所有成員函式，其中 string 是 std::basic_string 的簡寫：

構造表示
string:: string（構造）
string:: ~string（析構）
string:: operator= - 賦值
string:: assign –賦值
string:: get_allocator –獲得記憶體分配器
字元訪問
string:: at –訪問特定字元，帶邊界檢查
string:: operator –訪問特定字元
string:: front –訪問第一個字元
string:: back –訪問最後一個字元
string:: data –訪問基礎陣列，C++11 後與 c_str 完全相同
string:: c_str –返回對應於字串內容的 C 風格零結尾的只讀字串
string:: substr –以子串構造一個新串；引數為空時取全部源串
迭代器
string:: begin –獲得指向開始位置的迭代器
string:: end –獲得指向末尾的迭代器
string:: rbegin –獲得指向末尾的逆向迭代器
string:: rend –獲得指向開始位置的逆向迭代器
string:: cbegin –獲得指向開始位置的只讀迭代器
string:: cend –獲得指向末尾的只讀迭代器
string:: crbegin –獲得指向末尾的逆向只讀迭代器
string:: crend –獲得指向開始位置的逆向只讀迭代器
容量
string:: empty –檢查是否為空
string:: size –返回資料的字元長度
string:: length –返回資料的字元長度，與 size 完全相同
string:: max_size –返回可儲存的最大的位元組容量，在 32 位 Windows 上大概為 43 億位元組。
string:: reserve –改變 string 的字元儲存容量，實際獲得的儲存容量不小於 reserve 的引數值。
string:: capacity –返回當前的字元儲存容量
string:: shrinktofit（C++11 新增）–降低記憶體容量到剛好
修改器
string:: clear –清空內容
string:: insert –插入字元或字串。目標 string 中的插入位置可用整數值或迭代器表示。如果引數僅為一個迭代器，則在其所指位置插入 0 值。
string:: erase –刪除 1 個或 1 段字元
string:: push_back –追加 1 個字元
string:: pop_back –刪除最後 1 個字元，C++11 標準引入
string:: append –追加字元或字串
string:: operator+= –追加，只有一個引數 —— 字元指標、字元或字串；不像 append 一樣可以追加引數的子串或若干相同字元
string:: copy –複製出一段字元到 C 風格字元陣列；有溢位危險
string:: resize –改變（增加或減少）字串長度；如果增加了字串長度，新字元預設為 0 值
string:: swap –與另一個 string 交換內容
string:: replace –替換子串；如果替換源資料與被替換資料的長度不等，則結果字串的長度發生改變
搜尋
string:: find –前向搜尋特定子串的第一次出現
string:: rfind –從尾部開始，後向搜尋特定子串的第一次出現
string:: findfirstof –搜尋指定字元集合中任意字元在 *this 中的第一次出現
string:: findlastof –搜尋指定字元集合中任意字元在 *this 中的最後一次出現
string:: findfirstnot_of –*this 中的不屬於指定字元集合的首個字元
string:: findlastnot_of –*this 中的不屬於指定字元集合的末個字元
string:: compare –與引數字串比較

1.4 常量值
string:: npos –表示 “未找到”，值為 static const unsigned -1

1.5 非成員的有關的全域性函式
std:: operator+ –字串連線
std:: operator!= –不等比較
std:: operator== –相等比較
std::http://en.cppreference.com/w/cpp/string/basicstring/operatorcmp operator –小於比較
std::http://en.cppreference.com/w/cpp/string/basicstring/operatorcmp operator –小於等於比較
std:: operator> –大於比較
std:: operator>= –大於等於比較
std::http://en.cppreference.com/w/cpp/string/basicstring/operatorltltgtgt operator –字串內容寫到輸出流中
std:: operator>> –從輸入流中讀取一個字串
std:: getline –從 istream 中讀入一行或一段字元到 string 中
std:: swap –交換兩個 string 的內容。是 std::swap 演算法針對 std::basic_string 的特化版本
std:: stoi –字串轉為整形
std:: stol –字串轉為長整形
std:: stoll –字串轉為長長整形
std:: stoul –字串轉為無符號長整形
std:: stoull –字串轉為無符號長長整形
std:: stof –字串轉為單精度浮點形
std:: stod –字串轉為雙精度浮點形
std:: stold –字串轉為長雙精度浮點形
std:: to_string –整型、無符號整型、浮點型轉化為 string
std:: to_wstring –整型、無符號整型、浮點型轉化為 wstring
std:: hash –計算 hash 值

1.6 字面量

C++14 標準定義瞭如下的 std::basic_string 字面量：

string operator "" s（const char *str, std::size_t len）;
u16string operator "" s（const char16t *str, std::sizet len）;
u32string operator "" s（const char32t *str, std::sizet len）;
wstring operator "" s（const wchart *str, std::sizet len）;

示例：

include

int main

{

using namespace std::string_literals;

std::string s2 = "abc\0\0def"; //forms the string "abc"

std::string s1 = "abc\0\0def"s; //form the string "abc\0\0def"

std::cout

1.7 構造 hash 值的函式

C++11 標準引入了 4 個 std::hash 函式模板的特化。用於以 string 為鍵值的 hash 定址。

template struct hash;

std::char_traits 類

chartraits 是一個 traits 類模板。用於抽象出給定字元型別的字元特性與字串操作。chartraits 用於明確（explicit）例項化一個 std::basic_string 類模板。

成員型別
char_type 	CharT
inttype 	可以保持 chartype 以及 EOF 的值的整數型別
off_type 	實現定義
pos_type 	實現定義
state_type 	實現定義
成員函式
assignstatic 賦值一個字元
eqstatic 比較兩個字元相等
ltstatic 比較兩個字元小於
movestatic 移動一個字元序列到另一個字元序列
copystatic 複製一個字元序列
comparestatic 詞典序比較兩個字元序列
lengthstatic 返回一個字元序列的長度
findstatic 在一個字元序列中找到一個字元
tochartypestatic 轉化整型值到相等的 char_type
tointtypestatic 轉化 char_type 到相等的整型值
eqinttypestatic 比較兩個整型值
eofstatic 返回 eof 值
not_eofstatic 檢查一個字元是否為 eof 值

例如，如果需要定義 “兩個字元相等” 當且僅當 “兩個字元的大寫形式相等”，就可以在 std::chartraits 之上派生定義一個類，過載定義 eq、lt、compare、find 四個靜態成員函式。再用此特性類作為第二個模板引數去例項化 std::basicstring 類模板。

C++11 放棄了 COW

從 C++11 開始，明確禁止用 “寫時複製”（Copy On Write）實現 stl::string。因為這在併發時容易引發錯誤。如下例的註釋：

include

int main

{std::string str1 ("hello world\n");

//p 指向 str1 的資料區

const char * p = str1.data ;

{

//str2 和 str1 共享資料

auto str2 (str1);

// 訪問導致 str1 複製資料，此時 p 和 str2 直線同一塊區域

str10;

//str2 離開作用域，呼叫解構函式，此時 str2 的 RefCount 為 0，因此 str2 指向的記憶體被釋放

}

// 此時 p 為野指標，這是嚴重的 bug

printf (p);

return 0;

}

小物件最佳化

現在的主流編譯器與標準庫基本都採用了小物件最佳化（small objects optimization，又叫 small buffer optimization），以節約動態分配記憶體開銷。

Visual C++：0 至 15 個位元組。在 release 版中，小字串緩衝區和儲存區指標複用為一個 union，再加上資料長度、資料區總長度，共計 24 個位元組（32 位非寬字元）或 32 個位元組（64 位非寬字元）；在 debug 中，小字串緩衝區和儲存區指標各有自己的儲存空間，因為共計 28 個位元組（32 位非寬字元）或 40 個位元組（64 位非寬字元）。
GCC >= 5：0 至 15 個位元組
clang:：0 至 22 個位元組

用法

include

int main

{

std::string foo = "fighters";

std::string bar = "stool";

// "!=" compares string contents for inequality, even though they are different objects.

if (foo != bar)

{

std::cout

由於字串的複製操作與其位元組長度成比例，是 O（n）量級。且建立字串的臨時棧物件的成本開銷。因此 string 一般作為常量引用（reference-to-const）以避免不必要的複製：

void printthestring (const std::string& str)

{

std::cout

c_str 成員函式返回 string 類的 C 語言風格字串（即 ASCII - 零串）的指標，用於 C 語言字串的互操作。如果不需要零結尾的字串，那麼成員函式 data 返回不一定是 0 結尾的字串的記憶體地址。