2011-07-28 70 views
6

我聲明變量string s;C++字符串使用最大緩衝區分配?

並做s = "abc";現在它有3個字符的緩衝區。

s = "abcd"後,它具有的4個字符的緩衝器。第三條語句

s = "ab"問題是將它保持的4個字符緩衝區還是會重新分配一個2字符緩衝區後,現在

如果它將分配2個字符的緩衝區有什麼辦法我可以告訴它保持分配的最大緩衝區。

那麼它保留了最大尺寸的緩衝區嗎?

s = "ab" 
s="abc" 
s="a" 
s="abcd" 
s="b" 

現在應該保持尺寸4.

的緩衝區是可能的嗎?

回答

7

s =「ab」的問題是它會保留4個字的緩衝區還是會 重新分配2個字緩衝區?

它不會重新分配緩衝區。我不知道它是否在標準中提到過,但是我見過的所有實現只有在需要重新分配時才需要增加的容量。永遠不要減少。即使您有一個包含4個字符的字符串並且致電.resize(2).reserve(2),容量也不會改變。爲了迫使字符串(或容器)重新分配內存以適應確切大小,有一個簡單的swap招爲

s.swap(string(s)); 

這裏會發生什麼?你從s中創建一個臨時的容器,其容量恰好等於s.size(),然後將它與原始字符串進行交換。臨時解析器將釋放所有必要的資源。

同樣,我不是聲稱這是標準的,但我見過的所有實現都有這種行爲。

+2

它取決於實現:如果給它分配一個新的字符串,容量較小,g ++將改變容量,而VC++通常會使用一組固定容量的最小容量。 (我懷疑你在考慮'std :: vector';你所描述的既不是g ++也不是VC++的行爲,我不能相信你都沒有見過這兩者。) –

10

字符串在分配後會保留其緩衝區,並且只在需要更大緩衝區時才重新分配。它也可能以大於3或4的初始緩衝區大小開始。

您可以使用capacity()成員函數檢查分配的大小。


後我下面詹姆斯的意見仍然相信我的答案是在這個問題給出的例子是正確的。

然而,對於一個參考計數執行的序列這樣

s = "some rather long string..."; 

std::string t = "b"; 
s = t; 

將設置s.capacity()爲等於t.capacity()如果實現決定共享st之間的內部緩衝器。

+0

所以在s =「b」之後它會保持5的大小正確嗎? –

+1

那麼'size()'是字符串中的字符數。即使分配了一個較小的字符串,它也會保持其「緩衝區容量()」。 –

+0

這非常依賴於實現,所描述的內容既不對應於VC++的行爲,也不對應於g ++的行爲。 –

0

您可以通過在不同時間致電 std::string::capacity輕鬆查看您的實施行爲。一般來說,如果任何實現有三個字符的緩衝區,我會很驚訝 。 (不 詞語,但字節,至少在最現代化的設備)。在實踐中, 實現而變化,並且還具體取決於新長度 如何產生:用克++,例如,用 std::string::erase除去字符不會降低字符串的容量,但 將分配一個新的,更小的字符串。無論哪種情況,VC++都不會減少容量 。 (一般情況下,VC++和g ++有非常不同的 戰略,在字符串中關於內存管理。)

編輯:

鑑於其他反應(這甚至不符合通常的 做法):這裏的小測試程序我用來驗證上述聲明我 (雖然我真的沒有需要它的G ++ —我知道實現的 內部相當不錯):

#include <string> 
#include <iostream> 
#include <iomanip> 

template<typename Traits> 
void 
test() 
{ 
    std::string s; 
    size_t lastSeen = -1; 
    std::cout << Traits::name() << ": Ascending:" << std::endl; 
    while (s.size() < 150) { 
     if (s.capacity() != lastSeen) { 
      std::cout << " " << std::setw(3) << s.size() 
       << ": " << std::setw(3) << s.capacity() << std::endl; 
      lastSeen = s.capacity(); 
     } 
     Traits::grow(s); 
    } 
    std::cout << Traits::name() << ": Descending: " << std::endl; 
    while (s.size() != 0) { 
     Traits::shrink(s); 
     if (s.capacity() != lastSeen) { 
      std::cout << " " << std::setw(3) << s.size() 
       << ": " << std::setw(3) << s.capacity() << std::endl; 
      lastSeen = s.capacity(); 
     } 
    } 
    std::cout << "Final: capacity = " << s.capacity() << std::endl; 
} 

struct Append 
{ 
    static void grow(std::string& s) 
    { 
     s += 'x'; 
    } 
    static void shrink(std::string& s) 
    { 
     s.erase(s.end() - 1); 
    } 
    static std::string name() 
    { 
     return "Append"; 
    } 
}; 

struct Assign 
{ 
    static void grow(std::string& s) 
    { 
     s = std::string(s.size() + 1, 'x'); 
    } 
    static void shrink(std::string& s) 
    { 
     s = std::string(s.size() - 1, 'x'); 
    } 
    static std::string name() 
    { 
     return "Assign"; 
    } 
}; 

int 
main() 
{ 
    test<Append>(); 
    test<Assign>(); 
    return 0; 
} 

試試吧。結果非常有益。