背景/概況
對(duì)自動(dòng)變量(“來自堆?!?的操作,這些變量是無需調(diào)用而創(chuàng)建的變量。malloc
/ new
)通常比涉及空閑存儲(chǔ)(“堆”)的速度快得多,后者是使用new
)。然而,自動(dòng)數(shù)組的大小在編譯時(shí)是固定的,但是來自空閑存儲(chǔ)的數(shù)組的大小則不是。此外,堆棧大小是有限的(通常是少數(shù)MIB),而空閑存儲(chǔ)僅受系統(tǒng)內(nèi)存的限制。
SSO是短/小字符串優(yōu)化。一個(gè)std::string
通常將字符串存儲(chǔ)為指向空閑存儲(chǔ)的指針(“堆”),它提供類似的性能特征,就像要調(diào)用new char [size]
..這可以防止非常大的字符串發(fā)生堆棧溢出,但速度可能會(huì)更慢,特別是對(duì)復(fù)制操作而言。作為一種優(yōu)化,許多實(shí)現(xiàn)的std::string
創(chuàng)建一個(gè)小的自動(dòng)數(shù)組,類似于char [20]
..如果您的字符串為20個(gè)或更小的字符(給定此示例,實(shí)際大小不同),則它將直接存儲(chǔ)在該數(shù)組中。這就避免了調(diào)用new
這會(huì)讓事情變得更快一些。
編輯:
我沒想到這個(gè)答案會(huì)如此流行,但既然如此,讓我給出一個(gè)更現(xiàn)實(shí)的實(shí)現(xiàn),但請(qǐng)注意,我從來沒有真正讀過任何SSO的實(shí)現(xiàn)“在野外”。
實(shí)施細(xì)節(jié)
至少,std::string
需要存儲(chǔ)以下信息:
大小可以存儲(chǔ)為std::string::size_type
或者是指向終點(diǎn)的指針。唯一的區(qū)別是用戶調(diào)用時(shí)是否需要減去兩個(gè)指針。size
或者添加一個(gè)size_type
當(dāng)用戶調(diào)用時(shí)指向指針。end
..容量也可以任意存儲(chǔ)。
你不用付錢。
首先,考慮基于以上概述的天真實(shí)現(xiàn):
class string {public:
// all 83 member functionsprivate:
std::unique_ptr<char[]> m_data;
size_type m_size;
size_type m_capacity;
std::array<char, 16> m_sso;};
對(duì)于64位系統(tǒng),這通常意味著std::string
每個(gè)字符串有24字節(jié)的“開銷”,另外還有16字節(jié)用于SSO緩沖區(qū)(此處選擇16字節(jié),而不是由于填充要求而選擇20字節(jié))。在我的簡(jiǎn)化示例中,存儲(chǔ)這三個(gè)數(shù)據(jù)成員加上一個(gè)本地字符數(shù)組是沒有意義的。如果m_size <= 16
,然后我會(huì)把所有的數(shù)據(jù)都放進(jìn)m_sso
,所以我已經(jīng)知道了容量,并且不需要指向數(shù)據(jù)的指針。如果m_size > 16
,那我就不需要m_sso
..在我需要它們的地方絕對(duì)沒有重疊之處。一個(gè)不會(huì)浪費(fèi)任何空間的更聰明的解決方案看起來會(huì)更像這樣(未經(jīng)測(cè)試,僅用于示例目的):
class string {public:
// all 83 member functionsprivate:
size_type m_size;
union {
class {
// This is probably better designed as an array-like class
std::unique_ptr<char[]> m_data;
size_type m_capacity;
} m_large;
std::array<char, sizeof(m_large)> m_small;
};};
我假設(shè)大多數(shù)實(shí)現(xiàn)都是這樣的。