C++17新特性之std::string_view
std::string_view系C++17標準發布后新增的內容,類成員變量包含兩個部分:字符串指針和字符串長度,相比std::string, std::string_view涵蓋了std::string的所有只讀接口。如果生成的std::string無需進行修改操作,可以把std::string轉換為std::string_view,std::string_view記錄了對應的字符串指針和偏移位置,無需管理內存,相對std::string擁有一份字符串拷貝,如字符串查找和拷貝,效率更高。
廢話不多說,上測試代碼:
#include "stdafx.h" #include <iostream> #include <string> #include <chrono> #include <string_view>class TimerWrapper { private:std::string str_type_;std::chrono::high_resolution_clock::time_point start_time_; public:TimerWrapper(const std::string& str_type) : str_type_(str_type){start_time_ = std::chrono::high_resolution_clock::now();}~TimerWrapper(){TimeCost();}void TimeCost(){auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - start_time_);std::cout << str_type_ << ", costtime: " << ms << std::endl;} };void TestString(const std::string& str) {std::cout << "string: " << str << std::endl;for (int i = 0; i < 1000000; i++){std::string sub_str = str.substr(5, 10);} }void TestStringView(const std::string_view& str_view) {std::cout << "str_view: " << str_view << std::endl;for (int i = 0; i < 1000000; i++){std::string_view sub_str_view = str_view.substr(5, 10);} }std::string_view PrintStringView() {std::string s = "How are you..";std::string_view str_view = s;return str_view; }int main() {std::string str = "abcdefghijklmnopqrtstuvwxyz";{TimerWrapper timer_wrapper("string");TestString(str);}{TimerWrapper timer_wrapper("stringview");std::string_view str_view = str;TestStringView(str_view);}std::string_view str_view_str = "testing string_view related..";std::string_view str_view_sub_str = str_view_str.substr(5, 10);std::cout << "str_view_sub_str: " << str_view_sub_str << "size: " << str_view_sub_str.size() << std::endl;std::cout << "str_view_str : " << str_view_str.data() << "size: " << str_view_str.size() << std::endl;//std::string strview2strerr = str_view_str; //報錯,不能直接轉換std::string strview2str = static_cast<std::string>(str_view_str);std::cout << "strview2str: " << strview2str << std::endl;std::cout << "PrintLocalStringView: " << PrintStringView() << std::endl; }先看看執行結果:
分析下代碼,我們做的第一個比較是std::string和std::string_view性能:
void TestString(const std::string& str) {std::cout << "string: " << str << std::endl;for (int i = 0; i < 1000000; i++){std::string sub_str = str.substr(5, 10);} }void TestStringView(const std::string_view& str_view) {std::cout << "str_view: " << str_view << std::endl;for (int i = 0; i < 1000000; i++){std::string_view sub_str_view = str_view.substr(5, 10);} }為方便數據比較,我們以執行1000000次為例,std::string因為操作過程中,會重新分配內存,生成一個對應的std::string副本,用時1065ms,std::string_view不持有字符串拷貝,與源字符串共享內存空間,其他是視圖,避免了std::string頻繁的字符串分配和拷貝操作,只用了85ms,效率顯而易見。
第二個測試,我們看看string_view的substr操作:
std::string_view str_view_str = "testing string_view related.."; std::string_view str_view_sub_str = str_view_str.substr(5, 10); std::cout << "str_view_sub_str: " << str_view_sub_str << "size: " << str_view_sub_str.size() << std::endl; std::cout << "str_view_str : " << str_view_str.data() << "size: " << str_view_str.size() << std::endl;截取后的字符串和size都是沒問題的,這個很容易理解,但是,當我們調用str_view_str.data()時,打印出來的是全字符串。這個是因為str_view_str還是指向的str_view_str,調用str_view_str.data()時,直至遇到結束符\0打印才結束,所以輸出的是整個源字符串。
此外,std::string的substr是線性復雜度,依賴于字符串長度, std::string_view的substr是常數復雜度,不依賴于字符串長度,std::string_view的substr的性能優于std::string的substr.
第三個問題,std::string和std::string_view轉換問題,調用 string_view構造器可將std::string轉換為string_view對象。std::string可隱式轉換為 std::string_view,正確的轉換可參考下圖:
//std::string strview2strerr = str_view_str; //報錯,不能直接轉換std::string strview2str = static_cast<std::string>(str_view_str); std::cout << "strview2str: " << strview2str << std::endl;第四個燙燙燙的問題:
std::cout << "PrintLocalStringView: " << PrintStringView() << std::endl;由于std::string_view并不持有字符串的內存,所以它的生命周期一定要比源字符串的生命周期長,源字符串被消毀,行為未定義。
總結
以上是生活随笔為你收集整理的C++17新特性之std::string_view的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: PP视频播放视频时如何关闭弹屏
- 下一篇: 【机器学习】3万字长文,PySpark入