複雜的GCC字符串池

    最近寫的一個程序,爲了使接口簡便,在返回字符串的時候不得已使用了stl::string,但是又擔心如果此方法被頻繁調用,可能會導致性能問題,於是嘗試用一些底層機制去優化stl::string。

    stl::string是怎麼實現的呢?腦海中有一個猜想,首先就是這樣:
class string
{
private:
    char* m_str;
    int m_len;
};

    爲了驗證這個想法,於是用sizeof(string)將類型的長度打出來看看…………結果讓人大跌眼鏡,還要我不戴眼睛!在GCC中,sizeof(string)=4。怎麼可能嘛?如果就四個字節,哪裏放長度信息呢?
    再次輸出更多信息來驗證:
         string str = "abcde";
        printf("addr=%08x, this=%08x, str=[%s]\n", (unsigned int)str.c_str(), *((unsigned int*)&str), str.c_str());
    string自身的四個字節存儲的內容竟然就是所指向的字符串的指針!!!

    難道?難道,string在GCC中的實現,就僅僅只是char*,如果調用str.length(),就是悄悄去調用strlen()?

    再寫一個輸入內存的16進制字符串的函數PrintHex(),用這個函數將內存中的信息打印出來,實現如下:
void PrintHex(char* Buffer, int Size, FILE* fp =stdout)
...{
    fprintf(fp, 
"===================================================== ");
    
char* p = NULL;
    
int i;
    
for (i=0, p = Buffer; i<Size; i++, p++)
    
...{
        fprintf(fp, 
"%02x ", (unsigned char)*p);
        
if (i%16==15)
        
...{
            fprintf(fp, 
" ");
        }

    }

    fprintf(fp, 
" ===================================================== ");
}

    打印一下內存的信息試試:
        string str="abcde";
        PrintHex(((char*)str.c_str())-20,  40);

    分析16進制字符串,大概明白點string的內部了,看懂的部分大約是這樣的:
struct string_buffer
{
    int Length;
    int Capacity;
    int unknown;
    char Content[_Capacity];  // _Capacity = Capacity
};

   而string只是指向這樣一個內存塊的content部分的指針。分配多個string,就會發現這些內存塊隔得很近。

   以上分析說明:
1、string只是指向字符串池中內容部分的一個指針;(將string作爲參數或者返回值,性能都很高,等同於const string&這樣的參數)
2、字符串池的塊中緩存了長度和預留空間等信息,所以,不要使用C的字符串函數來操作string的任何內容,結果可能不一致。

   最後,試試在VC中打印:sizeof(string),天哪!28個字節!微軟的STL實現,不敢恭維啊!


 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章