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