2015-09-23 207 views
19

std::string有幾個constructors。我正在尋找一種方法來避免重新分配,我很驚訝有一個填充構造函數,但沒有「保留」構造函數。爲什麼沒有爲std :: string保留構造函數?

std::string (size_t n, char c); 

但沒有

std::string (size_t n); 

所以我必須調用reserve()後,已分配的默認(對我來說16個字節),只是爲了重新分配立即呢?

有沒有這樣的構造函數來創建對象時直接保留空間的原因,而不是手動執行?或者我錯過了什麼,有什麼辦法可以做到這一點?

使用填充構造函數是在浪費時間,因爲它會遍歷內存只是被覆蓋,並且還導致了錯誤的大小,因爲s.length()報告N而不是0

+0

你確定每個默認的16字節是保留的嗎? ('sizeof(std :: string)'與此無關) – deviantfan

+3

@deviantfan,這是實現定義的 – SingerOfTheFall

+0

@SingerOfTheFall是的,就像16字節一樣。我特意表示Devolus的執行 – deviantfan

回答

3

這是所有猜測,但我會嘗試。

如果您已經知道所需字符串的大小,那麼您很可能會從其他地方複製數據,例如,從另一個字符串。在這種情況下,您可以調用其中一個接受char *const std::string &的構造函數立即複製數據。

另外,我看不出爲什麼在構建字符串之後使用reserve是一件壞事。雖然這是實現定義,我會假設它將使感此代碼:

std::string str; 
str.reserve(100); 

到總共100個元素,而不是116的分配存儲器(如在「第一分配16,然後釋放它們和再分配100個「),因此對不存在的保留構造函數沒有性能影響。

此外,如果你只是想一個空字符串沒有默認分配的一切,你大概可以使用std::string str(0, ' ');其無效的「使用填充構造函數是時間浪費」點。

+0

'std :: string str(0,'');'確實阻止了默認分配(VS2010)。我確信這只是在調試版本中發生的,所以它不會再成爲問題,但無論如何,這正是我所期待的。 – Devolus

+0

當'std :: string'爲默認構造函數提供了一些初始容量時,這是因爲它們只是內置了一些堆棧空間。沒有什麼特別的分配和釋放。 –

0

您基本上可以提出關於每個std::string方法的相同問題,該方法沒有體現爲構造函數。

例如,爲什麼我們沒有一個構造函數需要多個字符串,並將它們逐個添加到新創建的字符串中?

爲什麼不重載一個預留內存的構造函數會有很多原因。我認爲在面向對象的設置中,「保留內存字符串」的想法有點奇怪。該字符串表示一系列字符,而不是其後面的內存 - 這是實現細節,而不是主要功能。
當有人打開一家新餐廳時,他是否認爲「當這家餐廳最終開放時,在開幕的那一刻,我將爲所謂的100人組預訂100個座位,可能會或可能不會來!」

但你的問題隱含地陳述了一些非常不正當的東西:在C++中缺乏正確的緩衝區對象。你問儲備構造函數,因爲你想使用字符串作爲緩衝區,但零初始化它們是非常昂貴的。保留內存不會讓你寫超出字符串的大小。
所以這個問題的解決方案是使用unique_ptr<char[]>這不會零初始化字符,但會給你你正在尋找的RAII風格。

+0

我沒有看到unique_ptr對象在這裏如何幫助,因爲它沒有給我std :: string的功能。 – Devolus

+0

例如什麼功能? –

+0

例如:str + = txt; – Devolus

相關問題