簡體   English   中英

std :: basic_string構造函數如何預先知道要保留多少空間?

[英]How does the std::basic_string constructor know beforehand how much space to reserve?

std::basic_string具有以下構造函數,該構造函數使用s指向的以null結尾的字符串的內容初始化字符串:

std::basic_string(const CharT* s, const Allocator& alloc = Allocator());

但是構造函數如何事先知道為其內部緩沖區中的字符串保留多少空間?

我可以想到兩種方法:

1)它可以首先遍歷整個以null結尾的字符串,直到它找到第一個NULL字符,記住它遍歷了多少個字符,並將其用作其內部緩沖區的容量並開始復制。

缺點 :它必須讀取字符串兩次,一次用於計算字符,第二次用於復制字符串。

2)它可以在其內部緩沖區中保留一個保守的數量,然后開始復制。 如果它在緩沖區用完之前遇到NULL字符,我們就可以了,否則我們需要保留更多空間(再次保守一定數量),然后重復這些步驟。

缺點 :如果字符串相當大,不斷重新調整容量的開銷可能會變得明顯。

那么,理智的std :: basic_string實現做了什么(或者甚至在標准中指定了什么)?

常見的實現將遍歷原始字符串以計算長度,然后分配那么多空間。 它需要走兩次字符串,但這是一個快速的操作,在某些情況下有硬件支持,即使沒有硬件支持操作,它可能比單個內存分配便宜

第一種方法就是答案。 按照標准§21.4.2:

basic_string(const charT* s, const Allocator& a = Allocator());

9 效果:構造一個類basic_string的對象,並從長度為traits::length(s)的charT數組中確定其初始字符串值,其第一個元素由s指定...

10 備注:使用traits::length()

gcc的實現是:

  template<typename _CharT, typename _Traits, typename _Alloc>
    basic_string<_CharT, _Traits, _Alloc>::
    basic_string(const _CharT* __s, const _Alloc& __a)
    : _M_dataplus(_S_construct(__s, __s ? __s + traits_type::length(__s) :
                   __s + npos, __a), __a)
    { }

它使用traits_type::length ,類似於std::char_traits::length來發現c樣式的零終止字符串的長度。


如果你有一個巨大的輸入字符串來傳遞函數並且你有它的長度,你可以使用另一個重載來獲取大小並且不再計算它:

basic_string(const CharT* s, size_type count, ...)

你提到的第二種方法有另一個缺點,它必須縮小分配內存以停止浪費內存。 這種操作也很昂貴。

我想不出一個使用第二種方法的理智的實現。 某些實現(即Visual C ++)執行默認初始化,可以分配一些最小長度(例如1或16),然后調用assign ,它將獲取字符串的長度,必要時重新分配,然后復制字符串。

許多 - 如果不是全部 - 現代編譯器將使用手動調整的匯編語言來獲取以null結尾的字符串的長度,這通常非常快。 做一個allocate-copy-reallocate-copy-etc ......真是瘋了,至少在我所知道的所有平台上都是如此。

暫無
暫無

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

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