c++ std::ostringstream vs std::string::append

标签 c++ string stream

在所有使用某种缓冲的示例中,我看到他们使用流而不是字符串。 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/

相关文章:

c++ - 在样本外使用 libaws 时返回随机字符

string - 具有 PWideChar 参数的函数仅采用第一个字符

c++ - 从字符串中删除字符集

node.js - Node 请求(读取图像流 - 管道返回响应)

c++ - 用 nullptr 交换流缓冲区来模拟移动?

java 。对 Java 对象集合中的精确值进行分组和求和

C++以基类为输入访问派生类成员函数

c++ - 错误 : expected class-name before '{' token - can't seem to find any circular includes

c++ - 使用 libcurl 的 CA 证书身份验证

php - 如何验证一个字符串只包含小写字母?