整理了一些想法,拋磚引玉。

經(jīng)驗(yàn)大多基于 C++17,工作中不需要對 C 暴露接口,偶爾會(huì)使用 C 庫或者 C 風(fēng)格的接口,在與 C 交互上是半吊子水平。
std::string_view僅在 C++17 后才可用,對于沒有條件的項(xiàng)目,可以考慮使用 Abseil 等三房庫提供的string_view實(shí)現(xiàn),但要留意第三方的實(shí)現(xiàn)和std::string_view可能并不保證完全可互換。
首先是避免使用?std::string定義常量,在我的工作環(huán)境甚至?xí)粧呙韫ぞ邤r截。不使用原因包括:
std::string會(huì)引發(fā)堆內(nèi)存分配;std::string析構(gòu)函數(shù)非平凡,全局對象銷毀順序難以預(yù)測,存在生命周期結(jié)束后被訪問的風(fēng)險(xiǎn)(例如該?std::string被其他全局對象引用)等。近期搞的一些代碼,大家習(xí)慣是使用?constexpr?char[]:
constexpr char kMyConstString[] = "hello world";使用?constexpr char[]本身沒任何問題,只是很容易在調(diào)用中退化為?const char*,導(dǎo)致取字符串長度的復(fù)雜度變?yōu)?O(n)。為了避免計(jì)算長度的開銷,調(diào)用參數(shù)需要一路都額外帶一個(gè)?int或者?size_t的長度。
也見過一些其他代碼使用?std::string_view:
constexpr std::string_view kMyConstString = "hello world";
constexpr auto kMyConstString = "hello world"sv; // using namespace std::literalsstd::string_view自帶很多方法,自然比?constexpr char[]好用很多,也有 O(1) 的方法獲取長度。
通過字面量字符串創(chuàng)建的?std::string_view其內(nèi)部數(shù)據(jù)是 NUL 結(jié)尾的,但是 NUL 字符在其?size()之外,略有點(diǎn)怪怪的。但是一般意義上的?std::string_view不保證是 NUL 結(jié)尾的,導(dǎo)致用起來總需要多留個(gè)心眼。這種區(qū)別可能會(huì)導(dǎo)致開發(fā)時(shí)拿到一個(gè)?std::string_view后不知道該不該信任它有個(gè) NUL 字符而會(huì)腦裂,同時(shí)也會(huì)給 reviewer 帶來負(fù)擔(dān)。
遵循以下原則:
std::string_view(const) char*,通常都可以使用?std::string_view替代自底向上擴(kuò)散,是指使用最底層第一個(gè)不可變(e.g. 別人的庫)的調(diào)用參數(shù)作為參數(shù)類型傳遞。如果調(diào)用鏈靠下的部分是?const std::string&這樣的參數(shù)類型,那么直接保持?const std::string&到你負(fù)責(zé)的最外層即可。底層決定了參數(shù)必然需要轉(zhuǎn)換成為?std::string,假如調(diào)用鏈中間混進(jìn)了?std::string_view,就會(huì)導(dǎo)致需要從?std::string_view轉(zhuǎn)換?std::string,產(chǎn)生不必要的拷貝。
一個(gè)常見例子是,如果我的一個(gè)函數(shù)是查詢一個(gè)?std::map,這就決定了其查詢 key 必然是?std::string類型,查詢的?find()函數(shù)接收?const std::string&,遵循 “自底向上擴(kuò)散“ 原則,一路都應(yīng)該是?const std::string&。也就不難發(fā)現(xiàn),所有查?std::string為 key 的關(guān)聯(lián)容器的函數(shù),其參數(shù)最好都是?const std::string&。如果是調(diào)用別人的接口,接口使用了?const std::string&,則也是同理。
有一個(gè)例外是,如果底層的?std::string參數(shù)是值傳遞(而非引用、指針傳遞)的,例如:
void Foo(std::string s);那么無論如何也都會(huì)拷貝一次,此時(shí)也可以用?std::string_view做調(diào)用鏈傳遞。(但是,這種情況還是建議先看看是不是?Foo的參數(shù)應(yīng)該改成?const std::string&才對的,我見過的九成是從其他語言轉(zhuǎn)來的新手不知道引用,只有一成是函數(shù)內(nèi)部計(jì)算過程中要修改輸入作為臨時(shí)狀態(tài),于是干脆用值參數(shù)來做零時(shí)變量的拷貝。)
在?std::string_view和?const char*之間,鑒于 :
const char*數(shù)據(jù) +?int/size_t長度 】的組合可以和?std::string_view低成本互轉(zhuǎn),不用擔(dān)心發(fā)生數(shù)長度、拷貝;std::string_view可以低成本轉(zhuǎn)?const char*;const char*無法低成本轉(zhuǎn)?std::string_view,需要數(shù)一次長度 。考慮到?std::string_view用起來方便很多,通常在調(diào)用鏈上使用?std::string_view是更好的。
只有一種特殊情況,如果調(diào)用鏈底層的接口比較奇特,只接收單獨(dú)的?const char*(可能是寫死了在內(nèi)部數(shù)長度),并且調(diào)用參數(shù)來源也是個(gè)?const char*不知為何也不帶長度,那么遵循 “自底向上擴(kuò)散” 原則效能最佳,調(diào)用鏈過程中避免多數(shù)一次長度。
std::string與?std::string_view的最本質(zhì)區(qū)別是,前者持有字符串?dāng)?shù)據(jù)所在內(nèi)存的所有權(quán),并負(fù)責(zé)管理其生命周期,而后置只是對內(nèi)存中已有數(shù)據(jù)的引用。因而,僅在被引用字符串能夠保證生命周期足夠,且生命周期內(nèi)不會(huì)被修改時(shí),可以通過使用?std::string_view保存其引用或其片段的引用。
由于類(或者說對象)通常都是各自管理自己的成員,會(huì)發(fā)現(xiàn),上述使用?std::string_view的條件在類成員變量中很難滿足,就算見到,與其燒腦子梳理生命周期擔(dān)心以后會(huì)不會(huì)別人改崩,還是在遇到性能瓶頸之前先用?std::string是更保險(xiǎn)的做法,不要用正確性換取性能。相比其他場合,類成員變量使用?std::string_view通常風(fēng)險(xiǎn)高出很多。如果是我,甚至寧愿會(huì)優(yōu)先考慮共享語義,例如?std::shared_ptr,并在可能并發(fā)讀寫場合再加個(gè)鎖。
思路類似于(非靜態(tài))類成員變量,但類/對象通常承載了生命周期,而一個(gè)函數(shù)中的臨時(shí)變量通常沒有這種職責(zé),因此相比之下,臨時(shí)變量有更多的場合適合使用?std::string_view。
具體來說,如果函數(shù)調(diào)用,要么是同步無并發(fā)的,要么有只讀并發(fā)且能保證被引用數(shù)據(jù)生命周期的,就可以使用?std::string_view來引用數(shù)據(jù)。我傾向于僅在同步無并發(fā)的環(huán)境使用——并發(fā)環(huán)境冷不丁某一天可能就不是只讀并發(fā),或者生命周期有變化了。
在一些需要對字符串做算法處理的場合,例如很多字符串算法題,需要對字符串的字串進(jìn)行遞歸操作,若使用?std::string作為參數(shù)進(jìn)行遞歸,不可避免有大量拷貝。屏幕前的看官可以翻翻?LeetCode提交記錄,如果有使用?std::string的遞歸,可以試著改成?std::string_view,對比一下運(yùn)算時(shí)間和內(nèi)存,通常優(yōu)勢是比較明顯的。
你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機(jī)房具備T級流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級服務(wù)器適合批量采購,新人活動(dòng)首月15元起,快前往官網(wǎng)查看詳情吧
文章標(biāo)題:C++更常用string還是char*呢?-創(chuàng)新互聯(lián)
文章網(wǎng)址:http://www.chinadenli.net/article34/desese.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供動(dòng)態(tài)網(wǎng)站、Google、響應(yīng)式網(wǎng)站、用戶體驗(yàn)、網(wǎng)站策劃、ChatGPT
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容