std::string 没有空闲存储内存分配
非常相似的问题
我有一个与如何使用 glibc 的字符串实现在堆栈上分配 std::string ?
但我认为值得再次询问。
我想要一个带有本地存储的 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 个字节,然后调用::operator new()
。我无法让它发挥作用。在执行上面这行代码的过程中,我的 GCC 4.5 标准字符串库调用了 inline_allocator
的复制构造函数 4 次。我不清楚是否有一种明智的方法来为 inline_allocator
编写复制构造函数。
在另一个 StackOverflow 线程中,Eric Melski 提供了 Chromium 中的类的链接:
http://src.chromium.org/svn/trunk/src/base/stack_container.h
这很有趣,但它不是 std::string
的直接替代品,因为它将 std::basic_string
包装在容器中,因此您必须调用重载的 operator->()
才能获取 std:: basic_string
。
我找不到任何其他解决方案来解决这个问题。难道就没有什么好的解决办法吗?如果这是真的,那么 std::basic_string 和 std::allocator 概念是否存在严重缺陷?我的意思是,这似乎应该是 std::basic_string 和 std::allocator 的一个非常基本且简单的用例。我认为 std::allocator 概念主要是为池设计的,但我认为它也应该涵盖这一点。
如果重写字符串库以便 basic_string
使用移动,C++0x 中的右值引用移动语义似乎可以编写 inline_allocator
其分配器的构造函数而不是复制构造函数。有谁知道这个结果的前景如何?
我的应用程序需要每秒构造一百万个微小的 ASCII 字符串,因此我最终基于 Boost.Array
编写了自己的固定长度字符串类,它工作得很好,但这仍然困扰着我。
I have a question very similar to
How do I allocate a std::string on the stack using glibc's string implementation?
but I think it's worth asking again.
I want an std::string
with local storage that overflows into the free store. std::basic_string
provides an allocator as a template parameter, so it seems like the thing to do is to write an allocator with local storage and use it to parameterize the basic_string
, like so:
std::basic_string<
char,
std::char_traits<char>,
inline_allocator<char, 10>
>
x("test");
I tried to write the inline_allocator
class that would work the way you'd expect: it reserves 10 bytes for storage, and if the basic_string
needs more than 10 bytes, then it calls ::operator new()
. I couldn't get it to work. In the course of executing the above line of code, my GCC 4.5 standard string library calls the copy constructor for inline_allocator
4 times. It's not clear to me that there's a sensible way to write the copy constructor for inline_allocator
.
In the other StackOverflow thread, Eric Melski provided this link to a class in Chromium:
http://src.chromium.org/svn/trunk/src/base/stack_container.h
which is interesting, but it's not a drop-in replacement for std::string
, because it wraps the std::basic_string
in a container so that you have to call an overloaded operator->()
to get at the std::basic_string
.
I can't find any other solutions to this problem. Could it be that there is no good solution? And if that's true, then are the std::basic_string
and std::allocator
concepts badly flawed? I mean, it seems like this should be a very basic and simple use case for std::basic_string
and std::allocator
. I suppose the std::allocator
concept is designed primarily for pools, but I think it ought to cover this as well.
It seems like the rvalue-reference move semantics in C++0x might make it possible to write inline_allocator
, if the string library is re-written so that basic_string
uses the move constructor of its allocator instead of the copy constructor. Does anyone know what the prospect is for that outcome?
My application needs to construct a million tiny ASCII strings per second, so I ended up writing my own fixed-length string class based on Boost.Array
, which works fine, but this is still bothering me.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
Andrei Alexandrescu,杰出的 C++ 程序员,撰写了《现代 C++ 设计》,曾经写过一篇关于使用可定制存储系统构建不同字符串实现的精彩文章。他的文章(链接在此处)描述了如何执行上面描述的更通用系统的特殊情况,该系统可以处理各种巧妙的内存分配要求。这里并没有过多讨论 std::string ,而是更多地关注完全自定义的字符串类,但您可能想研究一下它,因为实现中存在一些真正的精华。
Andrei Alexandrescu, C++ programmer extraordinaire who wrote "Modern C++ Design" once wrote a great article about building different string implementations with customizable storage systems. His article (linked here) describes how you can do what you've described above as a special case of a much more general system that can handle all sorts of clever memory allocation requirements. This doesn't talk so much about
std::string
and focuses more on a completely customized string class, but you might want to look into it as there are some real gems in the implementation.C++2011 确实会为您提供帮助:)
事实上,C++03 中的分配器概念已被削弱。其中一个要求是
A
类型的分配器应该能够从任何其他类型A
的分配器中释放内存...不幸的是,这个要求也与有状态的要求不一致。每个分配器都挂接到自己的池上。Howard Hinnant(他管理 C++ 委员会的 STL 子组,并正在为 C++0x 从头开始实现新的 STL)探索了 他的网站上有基于堆栈的分配器,您可以从中获得灵感。
C++2011 is really going to help you here :)
The fact is that the
allocator
concept in C++03 was crippled. One of the requirement was that an allocator of typeA
should be able to deallocate memory from any other allocator from typeA
... Unfortunately this requirement is also at odds with stateful allocators each hooked to its own pool.Howard Hinnant (who manages the STL subgroup of the C++ commitee and is implementing a new STL from scratch for C++0x) has explored stack-based allocators on his website, which you could get inspiration from.
这通常是不必要的。它被称为“短字符串优化”,并且
std::string
的大多数实现已经包含它。它可能很难找到,但无论如何它通常都在那里。举例来说,以下是属于 MinGW 的
sso_string_base.h
的相关部分:_M_local_data
成员是相关的——它可以存储(最多)15 个数据的空间字符(加上 NUL 终止符),而不在堆上分配任何空间。如果没记错的话,VC++ 中包含的 Dinkumware 库分配了 20 个字符的空间,尽管我已经有一段时间没有查看了,所以我不能发誓(并且跟踪头中的大部分内容往往很痛苦,所以如果可以的话,我宁愿避免看)。
无论如何,我很有可能你已经参与了一种非常流行的消遣,即过早优化。
This is generally unnecessary. It's called the "short string optimization", and most implementations of
std::string
already include it. It may be hard to find, but it's usually there anyway.Just for example, here's the relevant piece of
sso_string_base.h
that's part of MinGW:The
_M_local_data
member is the relevant one -- space for it to store (up to) 15 characters (plus a NUL terminator) without allocating any space on the heap.If memory serves, the Dinkumware library included with VC++ allocates space for 20 characters, though it's been a while since I looked, so I can't swear to that (and tracking down much of anything in their headers tends to be a pain, so I prefer to avoid looking if I can).
In any case, I'd give good odds that you've been engaged in that all-too-popular pass-time known as premature optimization.
我相信 Chromium 的代码只是将东西包装到一个漂亮的 shell 中。但不使用 Chromium 包装容器也可以获得相同的效果。
由于分配器对象经常被复制,因此它需要保存指向内存的引用或指针。因此,您需要做的是创建存储缓冲区,创建分配器对象,然后使用分配器调用 std::string 构造函数。
它比使用包装类要繁琐得多,但应该得到相同的效果。
您可以查看详细方法的示例(在我关于堆栈向量的问题中仍然使用铬的东西。
I believe the code from Chromium just wraps things into a nice shell. But you can get the same effect without using the Chromium wrapper container.
Because the allocator object gets copied so often, it needs to hold a reference or pointer to the memory. So what you'd need to do is create the storage buffer, create the allocator object, then call the std::string constructor with the allocator.
It will be a lot wordier than using the wrapper class but should get the same effect.
You can see an example of the verbose method (still using the chromium stuff) in my question about stack vectors.