29

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

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

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

4

4 回答 4

10

你有没有分析过你的执行,并发现它们是减速的根源?

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

至于预留空间...

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

另一种选择可能是(未经测试!)

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

您可能会在这个gamedev 线程中找到更多想法。

编辑:

弄乱字符串流的 rdbuf也可能是一个解决方案。这种方法可能很容易出错,所以请确保它是绝对必要的。绝对不优雅或简洁。

于 2009-12-21T16:33:07.553 回答
4

尽管“弄乱字符串流的 rdbuf ......可能很容易出错”,但我还是继续进行了一个概念验证以获取乐趣,因为它一直困扰着我,没有简单的reserve存储方法为stringstream. 同样,正如@luke 所说,优化分析器告诉您需要优化的内容可能会更好,所以这只是为了解决“如果我仍然想这样做怎么办?”。

我没有使用stringstream 的 rdbuf,而是自己制作了,它的作用几乎相同。它只实现最小值,并使用 astring作为缓冲区。不要问我为什么叫它a VECTOR_output_stream。这只是一个快速破解的东西。

constexpr auto preallocated_size = 256;
auto stream = vector_output_stream(preallocated_size);
stream << "My parrot ate " << 3 << " cookies.";
cout << stream.str() << endl;
于 2019-12-23T17:25:40.150 回答
2

我不确定,但我怀疑stringbufofstringstream与 results 密切相关string。所以我怀疑你可以ss.seekp(reserved-1); ss.put('\0');用来保留reserved底层string的字节数ss。实际上我希望看​​到类似的东西ss.seekp(reserved); ss.trunc();,但是没有trunc()流的方法。

于 2013-01-02T23:28:49.950 回答
2

坏的

这是一个老问题,但即使在 C++1z/C++2a 中Visual Studio 2019stringstream也没有保留缓冲区的理想方法。

这个问题的其他答案根本不起作用,原因如下:

  • 对空字符串调用 reserve 会产生一个空字符串,因此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 is constructed with dummy. This copies the entire string's contents into an internal buffer, which is preallocated.
  • dummy is then cleared and then erased, freeing up its allocation.

This means that in order to preallocate a stringstream, two allocations, one fill, and one copy takes place. The worst part is that during the expression, twice as much memory is needed for the desired allocation. Yikes!

For most use cases, this might not matter at all and it's OK to take the extra fill and copy hit to have fewer reallocations.

于 2019-11-22T07:01:28.667 回答