2010-09-22 118 views
14

字符串結構中導致sizeof()爲32的開銷是多少?爲什麼sizeof(string)== 32?

+5

如果你打開你的平臺的''頭,你可以清楚地看到爲什麼'std :: string'是那麼大。 @Queso:'sizeof'產生一個對象_in bytes_的大小。 – 2010-09-22 15:22:31

+2

如果sizeof返回指針中的位數,那麼編譯器中斷 – 2010-09-22 15:23:35

+0

@Queso:sizeof()返回字節,而不是位。一個32字節的指針是一個256位的地址 – mkb 2010-09-22 15:23:36

回答

39

一些std::string實現將非常小的字符串直接保存在靜態大小的char數組中,而不是使用動態堆存儲。這樣可以避免大量小字符串對象的堆分配,並提高了引用的局部性。

此外,將會有一個std::size_t成員來保存字符串大小和一個(可能未使用,見上文)指向堆存儲器的指針。

+1

啊。爲什麼這是低調的? – 2010-09-22 15:50:53

+0

這似乎是我,但我沒有故意這樣做。對於那個很抱歉! – Bill 2010-09-22 16:20:07

+0

@賬單:沒有汗!我也發生過。 – 2010-09-22 16:25:42

9

std::string通常包含「小字符串優化」的緩衝區---如果字符串小於緩衝區大小,則不需要堆分配。

+0

其中「典型」==「在Windows上」;-) – 2010-09-22 15:52:39

+2

Windows編譯器並不是唯一能夠進行小字符串優化的人 – 2010-09-22 16:06:23

+0

當然,但如果您不願意給他們起名,那很難判斷這是是「典型的」行爲,或者只是以此爲理由,認爲這是普通實現(大概是其他實現)的行爲。 – 2010-09-22 16:13:03

3

它依賴於庫。您不應該依賴std::string對象的大小,因爲它可能會在不同的環境(顯然是不同的標準庫供應商之間,也可能是同一庫的不同版本之間)發生變化。

請記住,std::string實現是由優化了各種用例的人編寫的,通常導致2個內部表示,一個用於短字符串(小內部緩衝區),另一個用於長字符串(堆分配外部緩衝)。開銷與每個std::string對象中的這兩個對象相關聯。

4

我的猜測是:

class vector 
{ 
    char type; 
    struct Heap 
    { 
     char* start; 
     char* end; 
     char* allocatedEnd; 
    }; 
    struct Stack 
    { 
     char size; 
     char data[27]; 
    } 
    union 
    { 
     Stack stackVersion; 
     Heap heapVersion; 
    } version; 
}; 

但我敢打賭,有數以百計的做這件事的方式。

+0

awww ... no參考計數?摺疊發生了什麼? – 2017-05-16 20:07:54

+0

@ErikAronesty有一個階段是用'std :: string'嘗試引用計數,但很明顯他的效率不高(多年來有好幾篇文章),而短字符串優化變得流行起來。 – 2017-05-16 21:48:33

1

問:爲什麼狗是黃色的? 答:不一定。

(an?)std :: string對象的大小是依賴於實現的。我剛剛檢查了MS VC++ 2010.它確實使用了32個字節作爲std :: string。有一個16字節的聯合,它包含字符串的文本,如果它合適,或者指向堆存儲更長的字符串。如果實現者選擇在字符串對象而不是堆中保留18個字節的字符串,則大小爲34個字節。其他16個字節包含開銷,包含諸如字符串的長度和當前爲字符串分配的內存量等內容。

不同的實現可能總是從堆中分配內存。這樣的實現無疑需要更少的字符串對象的內存。

2

在克++ 5.2(在例如克++ 4.9,它是不同的)的字符串被基本上定義爲:

class string { 
    char* bufferp; 
    size_t length; 
    union { 
    char local_buffer[16]; 
    size_t capacity; 
    }; 
}; 

在普通的計算機這增加多達32個字節(8 + 8 + 16)。

實際的定義當然是

typedef basic_string<char> string; 

,但這個想法是一樣的。