如何使用glibc的字符串实现在堆栈上分配std :: string?

时间:2009-04-23 23:16:46

标签: c++ memory stack heap stdstring

int main(void)
{
   std::string foo("foo");
}

我的理解是上面的代码使用默认的allocator来调用new。因此,即使在堆栈上分配了std :: string foo,foo中的内部缓冲区也会在堆上分配。

如何创建完全在堆栈上分配的字符串?

5 个答案:

答案 0 :(得分:21)

我最近想自己做这件事并发现以下代码:

Chronium's stack_container.h

它定义了一个新的std::allocator,它可以为STL容器的初始存储分配提供基于堆栈的分配。我找到了一种不同的方法来解决我的特定问题,所以我实际上并没有自己使用代码,但也许它对你有用。请务必阅读代码中有关使用和警告的注释。

对于那些质疑这样做的实用性和理智性的人,请考虑:

  • 您经常知道您的字符串具有合理的最大大小。例如,如果字符串将存储十进制格式的32位整数,则您知道这样做不需要超过11个字符。在这种情况下,不需要能够动态增长到无限大小的字符串。
  • 在许多情况下,从堆栈中分配比从堆中分配更快。
  • 如果经常创建和销毁字符串(假设它是常用实用程序函数中的局部变量),则从堆栈而不是堆中分配将避免碎片导致堆分配器中的流失。对于使用大量内存的应用程序,这可能会改变游戏规则。

有些人评论说,使用基于堆栈的分配的字符串不会是std::string,就好像这会以某种方式降低其效用。是的,您不能互换使用这两者,因此您无法将stackstring传递给期望std::string的函数。但是(如果你做对了),你将可以使用stackstringstd::stringfind_first_of()使用的所有相同成员函数,例如append()begin()等等end()std::string仍然可以正常工作,因此您将能够使用许多STL算法。当然,从最严格的意义上说它不会是{{1}},但在实际意义上它仍然是一个“字符串”,它仍然会非常有用。

答案 1 :(得分:11)

问题是std::basic_string有一个分配器的模板参数。但std::string不是模板,也没有参数。

因此,您原则上可以使用std::basic_string的实例化,其中分配器使用堆栈上的内存,但它不是std::string。特别是,您不会获得运行时多态性,并且无法将生成的对象传递给期望std::string的函数。

答案 2 :(得分:4)

你做不到。除了...

std::string

的实例
std::basic_string<class CharType, 
                  class Traits=char_traits<CharType>, 
                  class Allocator=allocator<CharType> >

您可以想象定义一个使用alloca进行内存管理的Allocator类。只有当Allocator本身以及直接或间接调用它的basic_string方法都是inline时,这才有效。使用此分配器创建的basic_string对象不会 一个std::string,但它会(大部分)表现得像它一样。但是,这对于有限的收益来说是相当多的工作。具体来说,使用此类从函数返回值将是一个职业限制的举措。

我不知道为什么你或其他任何人想要这样做。

答案 3 :(得分:0)

我怀疑做这样的事情很难做到,我想知道你为什么要这样做?要在堆栈上完全分配一些东西,编译器需要在编译时知道事物的确切大小 - 在您的示例中,它不仅需要知道std::string元数据的大小,还需要知道大小字符串数据本身。这不是太灵活,你可能需要不同的字符串类型,这取决于你想要包含在其中的字符串数据的大小 - 而不是不可能做到,只是它会使事情变得复杂。

答案 4 :(得分:-3)

  • std :: string将始终使用new / delete管理它的内部存储。
  • 不确定为什么您的问题包含 glibc的字符串实现。 c ++标准库的字符串实现与 glibc 无关。
  • 在堆栈上存储字符串的唯一方法是在堆栈上使用C char数组(就像Shhnap概述的那样)。但这可能不是你想要的: - )