我有一个与
非常相似的问题How do I allocate a std::string on the stack using glibc's string implementation?
但我觉得值得再问一次。
我想要一个带有本地存储的std::string
溢出到免费商店。 std::basic_string
提供了一个分配器作为模板参数,因此看起来要做的就是编写一个带有本地存储的分配器并使用它来参数化basic_string
,如下所示:
std::basic_string<
char,
std::char_traits<char>,
inline_allocator<char, 10>
>
x("test");
我尝试编写可以按照您期望的方式工作的inline_allocator
类:它保留10个字节用于存储,如果basic_string
需要超过10个字节,则调用{{ 1}}。我无法让它发挥作用。在执行上面的代码行的过程中,我的GCC 4.5标准字符串库调用了::operator new()
4次的复制构造函数。我不清楚为inline_allocator
编写复制构造函数是否合理。
在另一个StackOverflow线程中,Eric Melski将此链接提供给Chromium中的一个类:
http://src.chromium.org/svn/trunk/src/base/stack_container.h
这很有意思,但它不是inline_allocator
的替代品,因为它将std::string
包装在容器中,因此您必须调用重载的std::basic_string
来获取operator->()
。
我找不到任何其他解决方案。难道没有好的解决方案吗?如果这是真的,那么std::basic_string
和std::basic_string
概念是否存在严重缺陷?我的意思是,似乎这应该是std::allocator
和std::basic_string
的一个非常基本和简单的用例。我认为std::allocator
概念主要是为池设计的,但我认为它也应该涵盖这个。
如果重写了字符串库,那么C ++ 0x中的rvalue-reference移动语义似乎可以编写std::allocator
,以便inline_allocator
使用其移动构造函数allocator而不是copy构造函数。有谁知道这个结果的前景如何?
我的应用程序需要每秒构建一百万个微小的ASCII字符串,所以我最终根据basic_string
编写了我自己的固定长度字符串类,它工作正常,但这仍然困扰着我。
答案 0 :(得分:16)
编写“现代C ++设计”的C ++程序员非凡的Andrei Alexandrescu曾写过一篇关于使用可定制存储系统构建不同字符串实现的精彩文章。他的文章(linked here)描述了如何将上面描述的内容作为一个更通用的系统的特例,它可以处理各种聪明的内存分配要求。这并没有谈论std::string
,而是更多地关注完全自定义的字符串类,但您可能希望调查它,因为实现中有一些真正的宝石。
答案 1 :(得分:10)
C ++ 2011真的会帮助你:)
事实上,C ++ 03中的allocator
概念已经瘫痪了。其中一个要求是类型为A
的分配器应该能够从类型A
中的任何其他分配器释放内存...不幸的是,这个要求也与每个连接到它自己的有状态分配器不一致池。
答案 2 :(得分:6)
这通常是不必要的。它被称为“短字符串优化”,std::string
的大多数实现已经包含它。它可能很难找到,但无论如何它通常都存在。
仅举例来说,这是MinGW中sso_string_base.h
的相关部分:
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个字符分配空间,虽然我看了一段时间,所以我不能发誓(并且追踪其标题中的大部分内容往往是痛苦,所以我宁愿避免看我是否可以)。
在任何情况下,我都会给你很好的机会,因为你已经参与过那种非常流行的传递时间,称为过早优化。
答案 3 :(得分:2)
我相信来自Chromium的代码只是把东西包装成一个漂亮的shell。但是,如果不使用Chromium包装容器,您可以获得相同的效果。
因为allocator对象经常被复制,所以它需要保存一个引用或指向内存的指针。所以你需要做的是创建存储缓冲区,创建allocator对象,然后用分配器调用std :: string构造函数。
与使用包装类相比,它会更加冗长,但应该会产生相同的效果。