我应该预先分配std :: stringstream吗?

问题描述 投票:22回答:3

我广泛使用std::stringstream在我的应用程序中构造字符串和错误消息。 stringstreams通常是寿命很短的自动变量。

这样的用法会导致为每个变量重新分配堆吗?我应该从临时变量切换为类成员stringstream变量吗?

在后一种情况下,如何保留stringstream缓冲区? (我应该使用足够大的字符串来初始化它,还是有一个更优雅的方法?)

c++ stl stringstream
3个回答
10
投票

您是否描述了您的执行情况,并发现它们导致运行速度降低?

考虑它们的用法。它们主要是针对正常代码流之外的错误消息吗?

至于保留空间...

一些实现可能会在为字符串流进行任何分配之前保留一个小的缓冲区。 std :: string的许多实现都可以做到这一点。

另一个选项可能是(未试用!)

std::string str;
str.reserve(50);
std::stringstream sstr(str);

您可能会在此gamedev thread中找到更多想法。

编辑:

stringstream's rdbuf摆弄也是一种解决方案。这种方法可能很容易出错,所以请be sure it's absolutely necessary。绝对不是优雅或简洁。


2
投票

我不确定,但是我怀疑stringbufstringstream与结果string紧密相关。因此,我怀疑您可以使用ss.seekp(reserved-1); ss.put('\0');reserved的基础string中保留ss个字节。实际上,我希望看到类似ss.seekp(reserved); ss.trunc();的内容,但是没有用于流的trunc()方法。


0
投票

坏人

这是一个古老的问题,但是就Visual Studio 2019中的C ++ 1z / C ++ 2a而言,stringstream也不是保留缓冲区的理想方法。

由于以下原因,此问题的其他答案根本不起作用:

  • 在一个空字符串上的调用保留会产生一个空字符串,因此stringstream构造函数不需要分配以复制该字符串的内容。

  • [seekp上的stringstream仍然似乎是未定义的行为和/或什么也不做。

善良

此代码段按预期工作,并且已根据请求的大小预先分配了ss

std::string dummy(reserve, '\0');
std::stringstream ss(dummy);
dummy.clear();
dummy.shrink_to_fit();

代码也可以写为单行std::stringstream ss(std::string(reserve, '\0'));

丑陋

此代码段中实际发生的是以下内容:

  • [dummy被预分配了保留,随后缓冲区中填充了空字节(构造函数必需)。
  • stringstream用伪造。这会将整个字符串的内容复制到预先分配的内部缓冲区中。
  • 然后清除[dummy,然后将其擦除,以释放其分配。

这意味着为了预分配stringstream,需要进行两次分配,一次填充和一份副本。最糟糕的部分是在表达式期间,所需分配需要两倍的内存。 kes!

对于大多数用例,这可能根本没有关系,可以采取额外的填充和复制命中以减少重新分配。

© www.soinside.com 2019 - 2024. All rights reserved.