一直以來廣大c++使用者對標準庫中std::string褒貶不一,筆者整理了一下,大致是以下幾點
不支援一些常用功能,例如format
有algorithm的情況下.basic_string支援的功能太多,過於冗餘,
缺少編碼資訊,對於寬位元組等有其它的容器,比如wstring,u16string,u32string.
不少地方效率不夠
比起字串更應該叫位元組串,它並不像其他語言一樣唯讀的(string_view).…
種種原因使得我的內心充滿了疑惑,所以決定欣賞下庫的**,我們開始吧
我們首先來看看string到底是什麼
template
<
class
_chart
>
struct char_traits;
template
<
>
struct char_traits<
char
>
;#ifdef _glibcxx_use_wchar_t
template
<
>
struct char_traits<
wchar_t
>
;#endif
#if ((__cplusplus >= 201103l) \
&& defined(_glibcxx_use_c99_stdint_tr1))
template
<
>
struct char_traits<
char16_t
>
;template
<
>
struct char_traits<
char32_t
>
;#endif
_glibcxx_begin_namespace_cxx11
template
<
typename _chart,
typename _traits = char_traits<_chart>
,typename _alloc = allocator<_chart>
>
class
basic_string
;/// a string of @c char
typedef basic_string<
char
> string;
#ifdef _glibcxx_use_wchar_t
/// a string of @c wchar_t
typedef basic_string<
wchar_t
> wstring;
#endif
#if ((__cplusplus >= 201103l) \
&& defined(_glibcxx_use_c99_stdint_tr1))
/// a string of @c char16_t
typedef basic_string<
char16_t
> u16string;
/// a string of @c char32_t
typedef basic_string<
char32_t
> u32string;
#endif
我們終於看到了string的真面目,其實string不是乙個單獨的類 它只不過是basic_string這個模板的乙個例項而已,
我們再來看看basic_string是什麼
template
<
typename _chart,
typename _traits,
typename _alloc>
class
basic_string
我們可以看到basic_string模板有三個引數 乙個是前面提到的型別,乙個是traits,乙個是alloc
我們乙個乙個來說 首先說說traits,我們可以看到在上面的第一欄**中給traits的型別的char_traits,那麼這究竟是什麼呢,我們來看看char_traits的宣告
template
<
typename _chart>
struct char_traits
我們看到其實就是一些型別的宣告 剩下的函式就是一些簡單的字元操作
我們再來看看char_traits< char>
template
<
>
struct char_traits<
char
>
static _glibcxx_constexpr booleq(
const char_type& __c1,
const char_type& __c2) _glibcxx_noexcept
....
.}
其實char型別就是乙個全特化 其實不僅是char型別的有特化 char16_t,char32_t等也都有 至於為什麼要給不同的型別有特化 原因就是比較中的memcmp函式使用了不同的版本.
到這裡我們算是清楚了三個模板引數中乙個的含義,就是char_traits,其作用就是對簡單的低階字串操作進行封裝
其實剩下的引數就不必多說,乙個是必要的型別,乙個是alloctor.
我們來細細看看basic_string的內部資料
template
<
typename _chart,
typename _traits,
typename _alloc>
class
basic_string
#else
_alloc_hider
(pointer __dat,
const _alloc& __a)
:allocator_type
(__a)
,_m_p
(__dat)
_alloc_hider
(pointer __dat, _alloc&& __a =
_alloc()
):allocator_type
(std::
move
(__a)),
_m_p
(__dat)
#endif
pointer _m_p;
// the actual data.};
_alloc_hider _m_dataplus;
size_type _m_string_length;
enum
;union..
....
};
其實自npos 前面的型別宣告簡單的了解的話大可不必深究,因為其應用都是有場景的,用的時候自會出現,沒有必有把這個過程反過來去學習,
首先我們看第乙個資料_m_dataplus這個其實就是乙個資料的封裝,把alloctor和string的源資料存放在一起,方便管理,在c++11後支援了右值,
第二個引數就是_m_string_length這個也很好理解,就是當前資料的有效長度,因為指標是從alloctor分配來的,資料不一定會把所有的資料域佔滿
第三個引數就比較有意思了_s_local_capacity本地容量? 奇怪的名字,我們的資料不都是從alloctor中來的嗎,為什麼會出現乙個本地容量, 這就是string的核心之一 就是短字串優化,我們可以看看下乙個資料,乙個聯合體,其中有乙個引數我們要多加注意,_m_local_buf[_s_local_capacity + 1],奇怪,為什麼string中會有乙個靜態陣列呢,其實這就是短字串優化,當string中的資料較小時,把資料儲存在靜態陣列中,alloctor就不必進行一次記憶體分配,從而減少一次系統呼叫,減少一次使用者態向核心態的轉換,這就是短字串優化,
最後再來看看_m_allocated_capacity這個引數,其含義就是容量,也就是分配的記憶體大小,很巧妙的設計,當使用靜態記憶體的時候,容量為15,不用計算,當大於15的時候靜態陣列便沒有用了,正好用來記錄容量,至於如何區分使用的記憶體是靜態的還是由alloctor分配的,就是我們的_m_dataplus要做的事了,其中有乙個指標,指向資料,我們只需要在進行短字串優化時把指標指向靜態陣列即可
以上就是string的體系結構部分
原始碼剖析 Hashtable 原始碼剖析
hashtable同樣是基於雜湊表實現的,同樣每個元素都是key value對,其內部也是通過單鏈表解決衝突問題,容量不足 超過了閾值 時,同樣會自動增長。hashtable也是jdk1.0引入的類,是執行緒安全的,能用於多執行緒環境中。hashtable同樣實現了serializable介面,它支...
《STL原始碼剖析》筆記 1
第一章 stl概論與版本簡介 一 臨時物件的產生與運用。p36 這裡的臨時物件,指的是一種無名物件 unnamed subjects 如果它們的產生不在程式設計師的預料之下,往往造成效率的負擔,但有時刻意製造臨時物件會讓程式乾淨清爽。刻意製造臨時物件的方法是,在型別名稱後直接加一對小括號,並可指定初...
nginx原始碼剖析 1 概要
用 剖析 這個詞語有點大言不慚了。一直對伺服器程式設計感興趣,選擇nginx作為分析的物件是因為其效率比較高,量也比較合適 10w行左右 質量高,作者對效率要求非常高,對 也有異乎尋常的潔癖。打算寫成乙個系列,但是本人文件水平一直偏弱,而且寫在這裡主要目的也只是為了當作學習筆記記錄,所以如果各位看官...