簡體   English   中英

如何實現std :: string?

[英]How is std::string implemented?

我很想知道如何實現std :: string以及它與c字符串的區別?如果標准沒有指定任何實現,那么任何帶有解釋的實現都會很好,它如何滿足標准給出的字符串要求?

實際上我使用的每個編譯器都為運行時提供了源代碼 - 因此無論您使用的是GCC還是MSVC,您都可以查看實現。 但是, std::string大部分或全部將被實現為模板代碼,這會導致非常難以閱讀。

Scott Meyer的書,Effective STL ,有一章關於std :: string實現,這是對常見變體的一個很好的概述:“第15項:注意string實現的變化”。

他談到了4種變化:

  • 關於引用計數的實現的幾種變體(通常稱為寫入時的復制) - 當字符串對象未被更改時,refcount會遞增,但實際的字符串數據不會。 兩個對象都指向相同的refcounted數據,直到其中一個對象修改它,導致數據的“寫入時復制”。 這些變化存在於諸如引用計數,鎖等之類的位置。

  • “短字符串優化”(SSO)實現。 在此變體中,對象包含通常指向數據,長度,動態分配緩沖區大小等的指針。但是如果字符串足夠短,它將使用該區域來保存字符串而不是動態分配緩沖區

此外, Herb Sutter的“更多例外C ++”有一個附錄(附錄A:“不是(在多線程世界中)的優化”),討論了為什么復制寫入refcounted實現由於同步問題經常在多線程應用程序中出現性能問題。 那篇文章也可在線獲取(但我不確定它是否與書中的內容完全相同):

這兩章都值得一讀。

std :: string是一個包裝某種內部緩沖區的類,並提供了操作該緩沖區的方法。

C中的字符串只是一個字符數組

解釋std :: string如何在這里工作的所有細微差別將花費太長時間。 也許看看gcc源代碼http://gcc.gnu.org ,看看他們究竟是怎么做的。

這個頁面的答案中有一個示例實現。

此外,假設您已安裝gcc,您可以查看gcc的實現。 如果沒有,您可以通過SVN訪問他們的源代碼 大多數std :: string是由basic_string實現的,所以從那里開始。

另一個可能的信息來源是Watcom的編譯器

字符串的c ++解決方案與c版本完全不同。 第一個也是最重要的區別是當c使用ASCIIZ解決方案時,std :: string和std :: wstring使用兩個迭代器(指針)來存儲實際的字符串。 字符串類的基本用法提供了動態分配的解決方案,因此在動態內存處理的CPU開銷成本中,它使字符串處理更加舒適。

您可能已經知道,C不包含任何內置的通用字符串類型,只通過標准庫提供幾個字符串操作。 C ++提供包裝功能的C和C ++之間的主要區別之一,因此它可以被視為偽造的泛型類型。

在C中你需要遍歷字符串,如果你想知道它的長度,std :: string :: size()成員函數基本上只有一條指令(結束 - 開始)。 只要有內存,就可以安全地將字符串附加到另一個字符串,因此無需擔心緩沖區溢出錯誤(以及漏洞),因為如果需要,附加會創建更大的緩沖區。

正如之前有人告訴的那樣,字符串是以模板化的方式從向量功能派生出來的,因此更容易處理多字節字符系統。 您可以使用typedef std :: basic_string specific_str_t定義自己的字符串類型; 表達式與模板參數中的任何仲裁數據類型。

我認為兩方都有足夠的優點和反差:

C ++字符串優點: - 在某些情況下更快的迭代(使用大小肯定,並且它不需要來自內存的數據來檢查你是否在字符串的末尾,比較兩個指針。這可能會對緩存) - 緩沖區操作包含字符串功能,因此不必擔心緩沖區問題。

C ++字符串缺點: - 由於動態內存分配的原因,基本用法可能會對性能產生影響。 (幸運的是,你可以告訴字符串對象應該是什么原始緩沖區大小,所以除非你超過它,否則它不會從內存中分配動態塊) - 與其他語言相比,通常是奇怪且不一致的名稱。 這對任何stl的東西都是壞事,但是你可以使用它,它會產生一些特定的C ++感覺。 - 模板的大量使用迫使標准庫使用基於頭的解決方案,因此它對編譯時間有很大影響。

這取決於您使用的標准庫。

例如, STLPort是一個C ++標准庫實現,它實現了字符串等。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM