在所有使用某种缓冲的示例中,我看到他们使用流而不是字符串。 std::ostringstream 和 << 运算符与使用 string.append 有何不同。哪个更快,哪个使用更少的资源(内存)。
我知道的一个区别是您可以将不同的类型输出到输出流中(如整数),而不是 string::append 接受的有限类型。
这是一个例子:
std::ostringstream os;
os << "Content-Type: " << contentType << ";charset=" << charset << "\r\n";
std::string header = os.str();
对
std::string header("Content-Type: ");
header.append(contentType);
header.append(";charset=");
header.append(charset);
header.append("\r\n");
显然使用流更短,但我认为 append 返回对字符串的引用,因此可以这样写:
std::string header("Content-Type: ");
header.append(contentType)
.append(";charset=")
.append(charset)
.append("\r\n");
你可以使用输出流:
std::string content;
...
os << "Content-Length: " << content.length() << "\r\n";
但是内存使用和速度呢?尤其是在大循环中使用时。
更新:
为了更清楚,问题是:我应该使用哪一个,为什么?是否存在一种首选的情况?对于性能和内存......好吧,我认为基准测试是唯一的方法,因为每个实现都可能不同。
更新 2:
嗯,我不清楚我应该从答案中使用什么,这意味着他们中的任何一个都可以完成这项工作,加上 vector 。 Cubbi
在添加了 Dietmar Kühl 的情况下做了很好的基准测试,最大的区别在于这些对象的构造。如果您正在寻找答案,您也应该检查一下。我会再等一下其他答案(查看以前的更新),如果我没有得到答案,我想我会接受 Tolga 的答案,因为他之前已经提出使用 vector 的建议,这意味着 vector 应该减少资源消耗。
最佳答案
构造一个流对象比构造一个字符串对象要复杂得多,因为它必须持有(并因此构造)它的std::locale
。成员,以及维护状态所需的其他内容(但语言环境在很大程度上是最重的)。
追加类似:两者都维护一个连续的字符数组,当超出容量时都分配更多。我能想到的唯一区别是,当附加到流时,每次溢出都会调用一个虚拟成员函数(除了内存分配/复制,它无论如何都会支配溢出处理)和 operator<<
必须对流状态进行一些额外的检查。
另外,请注意,您正在调用 str(),它会再次复制整个字符串一次,因此根据您编写的代码的用途,流示例会执行更多操作并且应该更慢。
让我们测试一下:
#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);
}
}
那是 1000 万次 重复
在我的 Linux 上,我得到了
stream string
g++ 4.8 7.9 seconds 4.4 seconds
clang++/libc++ 11.3 seconds 3.3 seconds
所以,对于这个用例,在这两个实现中,字符串似乎工作得更快,但显然两种方式都有很多改进(reserve() 字符串,将流构造移出循环,使用不'不需要复制来访问它的缓冲区等)
关于c++ std::ostringstream vs std::string::append,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19844858/