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