2011-03-30 89 views
33

我有非常相似的的std :: string沒有自由存儲內存分配

How do I allocate a std::string on the stack using glibc's string implementation?

一個問題,但我認爲這是值得再次詢問。

我想要一個std::string本地存儲溢出到免費商店。 std::basic_string提供一個allocator作爲模板參數,因此它似乎喜歡做的事是寫與本地存儲的分配和使用參數化basic_string,像這樣:

std::basic_string< 
char, 
std::char_traits<char>, 
inline_allocator<char, 10> 
> 
x("test"); 

我試着寫了inline_allocator類這將按照您的預期工作:它保留10個字節的存儲空間,如果basic_string需要超過10個字節,則它會調用::operator new()。我無法讓它工作。在執行上面這行代碼的過程中,我的GCC 4.5標準字符串庫調用inline_allocator的複製構造函數4次。我不清楚有沒有一種明智的方法來編寫inline_allocator的拷貝構造函數。

在其他StackOverflow的線程,埃裏克Melski提供此鏈接到一個類中鉻:

http://src.chromium.org/svn/trunk/src/base/stack_container.h

這是有趣的,但它不是一個簡易替換爲std::string,因爲它包裹std::basic_string在一個容器中,所以你必須打電話過載operator->()std::basic_string

我找不到解決此問題的其他解決方案。難道沒有好的解決方案嗎?如果這是真的,那麼std::basic_stringstd::allocator的概念是否存在嚴重缺陷?我的意思是,這似乎應該是一個非常基本和簡單的使用案例std::basic_stringstd::allocator。我想std::allocator這個概念主要是爲游泳池設計的,但我認爲它也應該涵蓋這個概念。

好像C++ 0x中右值引用移動語義,因此可能寫出inline_allocator,如果字符串庫重新編寫,以便basic_string使用其分配的移動構造函數,而不是拷貝構造函數。有誰知道這個結果的前景是什麼?

我的應用程序需要每秒鐘創建一百萬個微小的ASCII字符串,所以我最終編寫了基於Boost.Array的固定長度的字符串類,它工作正常,但這仍然困擾着我。

+0

有趣的問題,+1。 – 2011-03-30 21:44:21

+4

作爲過去與自定義分配器摔跤的人,我非常有興趣聽到權威人士就此主題發表看法。 – 2011-03-30 21:48:56

+0

+1「免費店鋪」。哦,因爲這是一個很好的問題。 – 2011-03-30 22:51:32

回答

16

編寫「Modern C++ Design」的C++程序員extraordinaire的Andrei Alexandrescu曾寫過一篇關於用可定製存儲系統構建不同字符串實現的精彩文章。他的文章(linked here)描述了你如何能夠完成上述描述,作爲一個更加通用的系統的特例,它可以處理各種聰明的內存分配需求。這並沒有多說關於std::string,而是更多地關注一個完全自定義的字符串類,但是您可能想要查看它,因爲實現中有一些真正的寶石。

+0

這是Alexandrescu的一篇很棒的文章,謝謝。對於如何爲basic_string定製存儲的問題,這是一個非常好的答案。 – 2011-03-30 23:35:41

2

我相信來自Chromium的代碼只是將東西包裝成一個漂亮的外殼。但是,您可以在不使用Chromium包裝容器的情況下獲得相同的效果。

因爲分配器對象經常被複制,所以它需要保存一個引用或指向內存的指針。所以你需要做的是創建存儲緩衝區,創建分配器對象,然後用分配器調用std :: string構造函數。

這將比使用包裝類更多的字,但應該得到相同的效果。

You can see an example of the verbose method (still using the chromium stuff) in my question about stack vectors

6

這通常是不必要的。它被稱爲「短字符串優化」,std::string的大多數實現已經包含它。它可能很難找到,但它通常是無論如何。

剛例如,這裏有sso_string_base.h相關一塊是MinGW的一部分:

enum { _S_local_capacity = 15 }; 

    union 
    { 
_CharT   _M_local_data[_S_local_capacity + 1]; 
size_type  _M_allocated_capacity; 
    }; 

_M_local_data件有關的一個 - 空間,它存儲(最多)15個字符(加上NUL終結者)而不在堆上分配任何空間。

如果沒記錯,附帶VC++的Dinkumware的庫20個字符分配空間,儘管它已經有一段時間,因爲我看了,所以我也不敢保證說(和跟蹤任何東西在他們的標題往往是一個痛苦,所以我寧願避免看我是否可以)。

在任何情況下,我都會給出很好的可能性,您會參與那種稱爲過早優化的非常流行的通行時間。

+1

VC++爲SSO分配16個字節,在我看來這太小了因爲'std :: wstring'在Windows代碼中比'std :: string'更常用,並且只允許在'std :: wstring'中有8個字符(如果是'.c_str()經常使用)。 – ildjarn 2011-03-30 23:04:02

+0

頭不屬於MinGW庫擴展(不是std :: string的一部分)嗎? – UncleBens 2011-03-30 23:14:53

+0

@UncleBens:我不這麼認爲,但我可能會誤解。還有一些替代品(例如STLPort,libC++)在'std :: string'的實現中肯定會使用SSO。 – 2011-03-30 23:29:35

10

C++ 2011是真的要幫助你在這裏:)

的事實是,allocator概念在C++ 03也殘廢了。其中一個要求是,A類型的分配器應該能夠從類型爲A的任何其他分配器中釋放內存......不幸的是,這種要求也與每個連接到自己池的有狀態分配器不一致。

霍華德Hinnant(欣南特)(誰管​​理的C++ commitee的STL組和正在實施從頭開始一個新的STL對C++ 0x中)已經探索stack-based allocators on his website,你能從中獲得靈感。

+1

這非常有趣。我查看了Hinnant的'stack_alloc'類,它對'std :: vector'很好,但對於'std :: basic_string'而言,效果不錯。我相信問題再次出現在'std :: basic_string'使用'stack_alloc'拷貝構造函數的方式中。 – 2011-03-31 13:22:16

+0

我認爲這是允許使用複製構造函數的方式,因爲您描述的要求。 – 2011-03-31 13:29:10

+0

@詹姆斯:是的,不幸的是,由於標準都暗示着分配器是無狀態的(或者至少所有相同類型的分配器或多或少都以某種方式共享相同的狀態),所以副本是完全允許的。 – 2011-03-31 13:35:21