时间:2019-05-06 标签:c++std::ostringstreamvsstd::string::append
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19844858/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
c++ std::ostringstream vs std::string::append
提问by NickSoft
In all examples that use some kind of buffering I see they use stream instead of string. How is std::ostringstream and << operator different than using string.append. Which one is faster and which one uses less resourses (memory).
在所有使用某种缓冲的示例中,我看到他们使用流而不是字符串。std::ostringstream 和 << 运算符与使用 string.append 有何不同。哪个更快,哪个使用更少的资源(内存)。
One difference I know is that you can output different types into output stream (like integer) rather than the limited types that string::append accepts.
我知道的一个区别是,您可以将不同类型输出到输出流(如整数)中,而不是 string::append 接受的有限类型。
Here is an example:
下面是一个例子:
std::ostringstream os;
os << "Content-Type: " << contentType << ";charset=" << charset << "\r\n";
std::string header = os.str();
vs
对比
std::string header("Content-Type: ");
header.append(contentType);
header.append(";charset=");
header.append(charset);
header.append("\r\n");
Obviously using stream is shorter, but I think append returns reference to the string so it can be written like this:
显然使用流更短,但我认为 append 返回对字符串的引用,因此可以这样写:
std::string header("Content-Type: ");
header.append(contentType)
.append(";charset=")
.append(charset)
.append("\r\n");
And with output stream you can do:
使用输出流,您可以执行以下操作:
std::string content;
...
os << "Content-Length: " << content.length() << "\r\n";
But what about memory usage and speed? Especially when used in a big loop.
但是内存使用和速度呢?特别是在大循环中使用时。
Update:
更新:
To be more clear the question is: Which one should I use and why? Is there situations when one is preferred or the other?For performance and memory ... well I think benchmark is the only way since every implementation could be different.
更清楚的问题是:我应该使用哪个,为什么?是否存在首选或另一种情况?对于性能和内存......好吧,我认为基准测试是唯一的方法,因为每个实现都可能不同。
Update 2:
更新 2:
Well I don't get clear idea what should I use from the answers which means that any of them will do the job, plus vector. Cubbi
did nice benchmark with the addition of Dietmar Kühl that the biggest difference is construction of those objects. If you are looking for an answer you should check that too. I'll wait a bit more for other answers (look previous update) and if I don't get one I think I'll accept Tolga's answer because his suggestion to use vector is already done before which means vector should be less resource hungry.
好吧,我不清楚我应该从答案中使用什么,这意味着他们中的任何一个都可以完成这项工作,再加上向量。 Cubbi
通过添加 Dietmar Kühl 做了很好的基准测试,最大的区别在于这些对象的构造。如果您正在寻找答案,您也应该检查一下。我将等待其他答案(查看以前的更新),如果我没有得到一个,我想我会接受 Tolga 的答案,因为他使用 vector 的建议之前已经完成,这意味着 vector 应该不那么需要资源。
采纳答案by Etherealone
std::ostringstream
is not necessarily stored as a sequential array of characters in memory. You would actually need to have continuous array of characters while sending those HTTP headers and that might copy/modify the internal buffer to make it sequential.
std::ostringstream
不一定以字符的顺序数组形式存储在内存中。在发送这些 HTTP 标头时,您实际上需要有连续的字符数组,这可能会复制/修改内部缓冲区以使其连续。
std::string
using appropriate std::string::reserve
has no reason to act slower than std::ostringstream
in this situation.
std::string
使用适当的std::string::reserve
没有理由std::ostringstream
在这种情况下行动得更慢。
However, std::ostringstream
is probably faster for appending if you absolutely have no idea about the size you have to reserve. If you use std::string
and your string grows, it eventually requires reallocation and copying of whole buffer. It would be better to use one std::ostringstream::str()
to make the data sequential at once compared to multiple re-allocations that would happen otherwise.
但是,std::ostringstream
如果您完全不知道必须保留的大小,则追加可能会更快。如果您使用std::string
并且您的字符串增长,它最终需要重新分配和复制整个缓冲区。std::ostringstream::str()
与否则会发生的多次重新分配相比,最好使用一个来使数据一次有序。
P.S. Pre-C++11 std::string
is not required to be sequential either, whilst almost all libraries implement it as sequential. You could risk it or use std::vector<char>
instead. You would need to use the following to do appending:
PS Pre-C++11std::string
也不需要是顺序的,而几乎所有的库都将它实现为顺序的。你可以冒险或使用它std::vector<char>
。您需要使用以下内容进行附加:
char str[] = ";charset=";
vector.insert(vector.end(), str, str + sizeof(str) - 1);
std::vector<char>
would be best for performance because it is most probably cheaper to construct, but it is probably not of importance compared to std::string
and the actual time they take to construct. I have done something similar to what you are trying and went with std::vector<char>
before. Purely because of logical reasons; vector seemed to fit the job better. You do not actually want string manipulations or such. Also, benchmarks I did later proved it to perform better or maybe it was only because I did not implement operations well enough with std::string
.
std::vector<char>
对性能来说是最好的,因为它很可能构建起来更便宜,但std::string
与构建它们所花费的实际时间相比,它可能并不重要。我做了一些类似于你std::vector<char>
之前尝试过的事情。纯粹是出于逻辑原因;vector 似乎更适合这份工作。您实际上并不想要字符串操作等。此外,我后来所做的基准测试证明它性能更好,或者可能只是因为我没有很好地使用std::string
.
While choosing, the container that has requirements for your needs and minimal extra features usually does the job best.
在选择时,对您的需求有要求且额外功能最少的容器通常最适合。
回答by Cubbi
constructinga stream object is a significantly more complex operation than constructing a string object, because it has to hold (and, therefore, construct) its std::locale
member, among other things needed to maintain state (but the locale is by a large margin the heaviest).
构造流对象是比构造字符串对象复杂得多的操作,因为它必须保存(并因此构造)其std::locale
成员,以及维护状态所需的其他内容(但语言环境在很大程度上是最重的) .
Appending is similar: both maintain a contiguous array of characters, both allocate more when the capacity is exceeded. The only differences I can think of is that when appending to a stream, there is one virtual member function call per overflow (in addition to memory allocation/copying, which dominates overflow handling anyway), and operator<<
has to do some extra checks of the stream state.
追加是相似的:两者都维护一个连续的字符数组,当超出容量时都分配更多。我能想到的唯一区别是,当附加到流时,每次溢出都会调用一个虚拟成员函数(除了内存分配/复制,无论如何它都支配着溢出处理),并且operator<<
必须对流进行一些额外的检查状态。
Also, note that you're calling str(), which copies the entire string one more time, so based on what your code is written to do, the stream example does more and should be slower.
另外,请注意,您正在调用 str(),它会再复制一次整个字符串,因此根据您编写代码的目的,流示例执行的操作更多,速度应该更慢。
Let's test:
让我们测试一下:
#include <sstream>
#include <string>
#include <numeric>
volatile unsigned int sink;
std::string contentType(50, ' ');
std::string charset(50, ' ');
int main()
{
for(long n = 0; n < 10000000; ++n)
{
#ifdef TEST_STREAM
std::ostringstream os;
os << "Content-Type: " << contentType << ";charset=" << charset << "\r\n";
std::string header = os.str();
#endif
#ifdef TEST_STRING
std::string header("Content-Type: ");
header.append(contentType);
header.append(";charset=");
header.append(charset);
header.append("\r\n");
#endif
sink += std::accumulate(header.begin(), header.end(), 0);
}
}
that's 10 millionrepetitions
那是1000 万次重复
On my Linux, I get
在我的 Linux 上,我得到
stream string
g++ 4.8 7.9 seconds 4.4 seconds
clang++/libc++ 11.3 seconds 3.3 seconds
so, for this use case, in these two implementations, strings appear to work faster, but obviously both ways have a lot to improve (reserve() the string, move stream construction out of the loop, use a stream that doesn't require copying to access its buffer, etc)
所以,对于这个用例,在这两个实现中,字符串似乎工作得更快,但显然这两种方法都有很多改进(保留()字符串,将流构造移出循环,使用不需要的流复制以访问其缓冲区等)
回答by Sorin
With stream you can have your class Myclass
override the <<
operation so that you can write
使用流,您可以让您的类Myclass
覆盖<<
操作,以便您可以编写
MyClass x;
ostringstream y;
y << x;
For append you need to have a ToString method (or something similar) since you can't override the append function of string.
对于追加,您需要有一个 ToString 方法(或类似的方法),因为您无法覆盖字符串的追加功能。
For some code pieces use whatever you feel more comfortable with. Use stream for bigger projects where it's useful to be able to simply stream an object.
对于某些代码片段,请使用您觉得更舒服的任何内容。将流用于能够简单地流式传输对象的大型项目。
回答by Slava
If you concern about speed you should profile and/or test. In theory std::string::append
should be not slower as it is simpler (stream has to deal with locale, different formatting and be more generic). But how faster one solution or another really is you can realize only by testing.
如果您担心速度,则应进行概要分析和/或测试。理论上std::string::append
应该不会更慢,因为它更简单(流必须处理语言环境、不同的格式并且更通用)。但是,只有通过测试才能意识到一种或另一种解决方案的速度有多快。