String (C++標準庫)

是C++標準程式庫中的一個頭文件，定義了C++標準中的字符串的基本模板類std::basic_string及相關的模板類實例： 
其中的string是以char作為模板參數的模板類實例，把字符串的內存管理責任由string負責而不是由編程者負責，大大減輕了C語言風格的字符串的麻煩。
std::basic_string提供了大量的字符串操作函數，如比較、連接、搜索、替換、獲得子串等。並可與C語言風格字符串雙向轉換。std::basic_string屬於C++ STL容器類，用戶自定義的類也可以作為它的模板參數，因此也適用C++ STL Algorithm庫。
string本質上是以字符作為元素的vector特化版本；不存在0字符結尾這個概念，能裝入'\0'這種數據。

**std::basic_string類模板**
std::basic_string類模板存儲且操縱類似char的對象的序列。該對象類型的性質由特性類模板std::char_traits的實例來提供，並作為std::basic_string的第二個模板參數。
C++11標準規定：basic_string的元素是連續存儲的。即對於basic_string 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 _Buf_BUF_SIZE;
_Elem *_Ptr;
} _Bx; 
size_type _Mysize;  // current length of string
size_type _Myres;   // current storage reserved for string
GCC從版本5開始，std::string不再採用COW策略。
C++17標準規定，basic_string是AllocatorAwareContainer, SequenceContainer與ContiguousContainer。

**模板參數**
CharT 	- 	字符類型
*Traits 	- 	字符的特性類
*Allocator 	內部存儲的分配器類

**成員類型**
traits_type 	模板參數Traits
*value_type 	即Traits::char_type
*allocator_type模板參數Allocator
*size_type 	即Allocator::size_type。C++11改為std::allocator_traits::size_type 
*difference_type即Allocator::difference_type。C++11改為std::allocator_traits::difference_type 
*reference 	即Allocator::reference。C++11改為value_type& 
*const_reference  即Allocator::const_reference。C++11改為const value_type&  
*pointer 	即Allocator::pointer。C++11改為std::allocator_traits::pointer 
*const_pointer 	即Allocator::const_pointer。C++11改為std::allocator_traits::const_pointer 
*iterator 	屬於RandomAccessIterator
*const_iterator 	屬於Constant random access iterator
*reverse_iterator 	即std::reverse_iterator
*const_reverse_iterator 	即std::reverse_iterator

**成員函數**
下面列出所有成員函數，其中 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:: shrink_to_fit（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:: find_first_of –搜索指定字符集合中任意字符在 *this 中的第一次出現
**string:: find_last_of –搜索指定字符集合中任意字符在 *this 中的最後一次出現
**string:: find_first_not_of –*this 中的不屬於指定字符集合的首個字符
**string:: find_last_not_of –*this 中的不屬於指定字符集合的末個字符
**string:: compare –與參數字符串比較

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

**非成員的有關的全局函數**
*std:: operator+ –字符串連接
**std:: operator!= –不等比較
**std:: operator== –相等比較
**std::http://en.cppreference.com/w/cpp/string/basic_string/operator_cmp operator –小於比較
**std::http://en.cppreference.com/w/cpp/string/basic_string/operator_cmp operator –小於等於比較
**std:: operator> –大於比較
**std:: operator>= –大於等於比較
**std::http://en.cppreference.com/w/cpp/string/basic_string/operator_ltltgtgt 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值
**std::  hash –計算hash值
**std::  hash –計算hash值
**std::  hash –計算hash值

**字面量**
C++14標準定義瞭如下的std::basic_string字面量：
*string operator "" s（const char *str, std::size_t len）; 
*u16string operator "" s（const char16_t *str, std::size_t len）; 
*u32string operator "" s（const char32_t *str, std::size_t len）; 
*wstring operator "" s（const wchar_t *str, std::size_t len）;
示例：
#include 
#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

**構造hash值的函數**
C++11標準引入了4個std::hash函數模板的特化。用於以string為鍵值的hash定址。
*template struct hash;
*template struct hash;
*template struct hash;
*template struct hash;

**std::char_traits類**
char_traits是一個traits類模板。用於抽象出給定字符類型的字符特性與字符串操作。char_traits用於明確（explicit）實例化一個std::basic_string類模板。 
*成員類型
**char_type 	CharT
**int_type 	可以保持char_type以及EOF的值的整數類型
**off_type 	實現定義
**pos_type 	實現定義
**state_type 	實現定義
*成員函數
**assignstatic賦值一個字符
**eqstatic     比較兩個字符相等
**ltstatic     比較兩個字符小於 
**movestatic   移動一個字符序列到另一個字符序列 
**copystatic   複製一個字符序列 
**comparestatic詞典序比較兩個字符序列 
**lengthstatic返回一個字符序列的長度 
**findstatic   在一個字符序列中找到一個字符 
**to_char_typestatic轉化整型值到相等的char_type
**to_int_typestatic  轉化char_type到相等的整型值 
**eq_int_typestatic  比較兩個整型值
**eofstatic     返回eof值
**not_eofstatic檢查一個字符是否為eof值 
例如，如果需要定義“兩個字符相等”當且僅當“兩個字符的大寫形式相等”，就可以在std::char_traits之上派生定義一個類，重載定義eq、lt、compare、find四個靜態成員函數。再用此特性類作為第二個模板參數去實例化std::basic_string類模板。

**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 
#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 print_the_string(const std::string& str)
{
std::cout 
c_str()成員函數返回string類的C語言風格字符串（即ASCII-零串）的指針，用於C語言字符串的互操作。如果不需要零結尾的字符串，那麼成員函數data()返回不一定是0結尾的字符串的內存地址。

**參考文獻==