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

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

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

4

5 回答 5

24

我最近想自己做这件事,发现以下代码很有启发性:

Chronium 的 stack_container.h

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

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

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

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

于 2009-04-24T02:37:26.673 回答
12

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

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

于 2009-04-23T23:32:07.710 回答
4

你不能。除了...

std::string是一个实例化

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

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

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

于 2009-04-23T23:36:40.633 回答
0

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

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