C++那些事之string那些事
C++11
C++17
C++20
C++23
結論
當我們使用C++時,庫的基礎知識比較熟悉,尤其是在C++中創建字符串時使用的std::string。這無疑是對舊的C風格“字符串”(使用以空字符結尾的字符數組)的一種改進。然而,C++標準庫在C++17和C++20中引入了更有用的組件,可以幫助你編寫更高效的代碼。
在頭文件中,std::basic_string類是一個模板類,為各種字符串類型提供了特化,包括常見字符串的std::string(即std::basic_string)和寬字符串的std::wstring(即std::basic_string<wchar_t>)。
還有一些固定寬度的特定字符串,比如std::u32string(即std::basic_string<char32_t>)和std::u16string(即std::basic_string<char16_t>)。
在C++20中,引入了char8_t,這也帶來了std::u8string(即std::basic_string<char8_t>)。我不知道為什么要等到C++20才引入char8_t,那么提個問題char16_t和char32_t在哪個標準存在呢?留言區見
注:本篇文章的所有代碼已同步至星球,更多優質內容一起探討。
C++11
在C++11標準下,字符串處理主要依賴于std::string
類,這是一個動態分配內存的字符串類。此外,引入了新的固定寬度字符串類型,如std::u32string
和std::u16string
,為處理Unicode字符提供了更好的支持。
#include?<iostream>
#include?<string>int?main()?{//?使用std::stringstd::string?str?=?"Hello,?C++11!";//?使用std::u32string和std::u16stringstd::u32string?u32str?=?U"Hello,?Unicode!";std::u16string?u16str?=?u"Hello,?Unicode!";std::cout?<<?str?<<?std::endl;std::wcout?<<?u32str?<<?std::endl;std::wcout?<<?u16str?<<?std::endl;return?0;
}
C++17
在C++17中,引入了<string_view>頭文件,提供了一種輕量級的只讀替代方案,用于使用頭文件中的字符串類型。這些字符串視圖類似于先前描述的字符串。例如,std::u32string的<string_view>等價物是std::u32string_view(即std::basic_string_view<char32_t>)。
這在需要讀取字符串但不需要修改它的函數中特別有用。與為函數創建字符串副本不同,我們可以簡單地查看現有字符串!此外,<string_view>非常靈活,不僅可以將C++樣式的字符串轉換為字符串視圖,甚至可以將C樣式的字符串轉換為字符串視圖。以下是演示std::string_view簡單用法的示例:
#include?<iostream>
#include?<string>
#include?<string_view>void?printString(std::string_view?str)?{std::cout?<<?str?<<?std::endl;
}int?main()?{std::string_view?strv{"strv"};?//?C++?string_viewprintString(strv);std::string?str{"str"};?//?C++?stringprintString(str);char?cstr[]?=?"cstr";?//?C-style?stringprintString(cstr);return?0;
}
輸出:
strv
str
cstr
在這個例子中,printString函數以std::string_view作為參數,這使得這個函數非常輕量級和靈活,因為沒有制作任何字符串的副本,這個函數可以通過傳遞C和C++樣式的字符串以各種方式使用。
C++20
在C++20中,引入了一些新的有用成員函數,包括starts_with(…)和ends_with(…)。正如名稱所示,這些函數確定一個字符串(或字符串視圖)是否以某個字符或某個std::string_view開頭/結尾。以下是一個簡單的例子:
#include?<cassert>
#include?<string>
#include?<string_view>int?main()?{const?std::string?str{"Hello?World!"};assert(str.starts_with('H'));assert(str.ends_with('!'));assert(str.starts_with("Hello"));?//?隱式轉換為std::string_viewassert(str.ends_with("World!"));?//?隱式轉換為std::string_viewreturn?0;
}
C++23
C++23中引入了contains
,用于檢查字符串是否包含指定的子字符串。
//?這是一個假設的C++23示例,實際上并不可用
#include?<iostream>
#include?<string>int?main()?{std::string?str?=?"C++23?introduces?contains?function.";if?(str.contains("introduces"))?{std::cout?<<?"The?string?contains?'introduces'."?<<?std::endl;}?else?{std::cout?<<?"The?string?does?not?contain?'introduces'."?<<?std::endl;}return?0;
}
https://en.cppreference.com/w/cpp/string/basic_string/contains
結論
在處理新的C++代碼中的字符串時,應考慮使代碼盡可能靈活和內存高效。使用<string_view>可以極大地幫助這些努力。此外,考慮使用最新的字符串成員函數,如starts_with和ends_with,以獲得可讀且易于實現的字符串解析代碼。而C++23使得contains計算更加簡單,越來越現代化了。