2016-07-29 253 views
7

不同的std ::向量的std :: string並沒有提供一個一元構造函數大小:std :: string(size,' 0')和s.resize(size)之間的區別?

std::string s(size); // ERROR 

是否有任何區別:

std::string s(size, '\0'); 

std::string s; 
s.resize(size); 

就其在常見實施方面的表現而言?

將調整大小將字符串初始化爲全部爲零的字符,還是將它留給未指定的值?

如果全零,是否有任何方法來構造給定大小的字符串,但留下未指定值的字符?

+0

什麼是size,size是0? –

+1

@FirstStep:不,其中'size'是一些'size_t',它是'> 0'。 –

+0

那麼你是否通過一個profiler來運行一些實現來衡量它們的性能? –

回答

4

有一個區別,如std::string s(size, '\0');,該字符串所需的所有內存可以一次分配。但是,對於第二個示例,如果size大於爲小字符串優化存儲的字符數量,則可能必須執行額外的分配,儘管這是實現定義的,並且在標準中關於此的肯定不會更高性能兼容的C++ 17實現。但是,第一個例子更加簡潔,可能更高效,因此可能更可取。當調用s.resize(size);時,所有新字符將被初始化爲char的默認構造函數,即'\0'。沒有辦法用未指定的值初始化string

+4

爲什麼在第二種情況下會有第二次分配?在這兩種情況下,如果'size'大於SSO緩衝區,則會有一個分配。 – Praetorian

+0

出於同樣的原因'make_unique()'更快,然後'new'調用並調用構造函數。在第一種情況下,所有內存'std :: string'需要可以一起分配。但是,在第二種情況下,'new'可能必須被調用兩次。這是我定義的實現,我將闡明。 – DeepCoder

+6

*出於和'make_unique()'更快,然後'new'調用和調用構造函數* ...一樣的原因,你在考慮'make_shared',因爲'make_unique'應該沒有區別。無論如何,我看到你假設默認構造'std :: string'會分配一次內存,這是非常不尋常的,但是允許的。但是,仍然認爲有差別似乎是錯誤的。有*可能*是有區別的,但很可能不是,除非你考慮初始化一些變量爲'0',然後改變它們,將它們初始化爲'size'開頭,這是一個區別。 – Praetorian

4

實際答案將基於實施,但我相當確信std::string s(size, '\0');更快。

std::string s; 
s.resize(size); 

根據documentation for std::string

1)默認構造函數。構造空字符串(零大小和未指定的容量)。

默認構造函數將創建一個「未指定容量」的字符串。我的感覺是,實現可以自由確定一個默認容量,可能在10-15個字符的範圍內(完全推測)。

然後在下一行,你會重新分配新size內存(resize)如果size比當前更大capacity。這可能不是你想要的!

如果你真的想明確地找到,你可以在這兩種方法上運行一個分析器。

2

DeepCoder已經有一個很好的答案。

然而,對於記錄,我想指出的是字符串(作爲載體),有兩個不同的概念:

  • size():它的實際(即有意義的)中的字符數串。你可以使用resize()來更改它(如果它不應該是'\0',你可以提供第二個參數來說明你想用作填充符的字符)
  • capacity():它是分配給字符串的字符數。至少它的大小,但可以更多。你可以增加它reserve()

如果你擔心分配表現,我相信最好玩的容量。大小應該真的保留字符串中的實際字符而不是填充字符。

順便說一下,更一般地說,s.resize(n)s.resize(n, char())相同。所以如果你想在施工時以相同的方式填充它,你可以考慮string s(n, char())。但只要你不使用basic_string<T>使T與字符不同,你的'\ 0'就是這樣做的。

1

調整大小不會使元素未初始化。根據文檔:​​

s.resize(size)將對每個附加字符進行值初始化。這將導致調整大小的字符串的每個元素被初始化爲'\0'

您將不得不衡量您特定C++實現的性能差異,以真正決定是否有值得區別。

查看由Visual C++生成的機器以獲得優化版本後,我可以告訴您任一版本的代碼量是相似的。看起來相反直觀的是resize()版本測量更快對我來說。不過,你應該檢查你自己的編譯器和標準庫。

相關問題