我正在编写一个嵌入式应用程序。在某些地方,我经常使用 std::ostringstream,因为它对我的目的非常方便。但是,我刚刚发现性能受到极大影响,因为向流中添加数据会导致对 malloc 和 free 的大量调用。有什么办法可以避免吗?
我的第一个想法是使 ostringstream 静态并使用 ostringstream::set("") 重置它。但是,这无法完成,因为我需要这些函数是可重入的。
我正在编写一个嵌入式应用程序。在某些地方,我经常使用 std::ostringstream,因为它对我的目的非常方便。但是,我刚刚发现性能受到极大影响,因为向流中添加数据会导致对 malloc 和 free 的大量调用。有什么办法可以避免吗?
我的第一个想法是使 ostringstream 静态并使用 ostringstream::set("") 重置它。但是,这无法完成,因为我需要这些函数是可重入的。
如果您在创建流之前知道数据有多大,则可以使用 ostrstream ,其构造函数可以将缓冲区作为参数。因此将没有数据的内存管理。
可能批准的处理方式是创建您自己的basic_stringbuf
对象以与您的ostringstream
. 为此,您有几个选择。一种是使用固定大小的缓冲区,并且overflow
当/如果您尝试创建太长的输出时就会失败。另一种可能性是使用向量作为缓冲区。与 std::string 不同,vector 保证附加数据将具有摊销常数复杂度。它也永远不会从缓冲区中释放数据,除非您强制它这样做,因此它通常会增长到您正在处理的最大大小。从那时起,它不应该分配或释放内存,除非您创建的字符串超出了它当前可用的长度。
好吧,Booger的解决方案是切换到sprintf()
. 它不安全且容易出错,但通常速度更快。
但并非总是如此。初始化后,我们不能在我的实时工作中使用它(或 ostringstream),因为它们都执行内存分配和释放。
我们解决这个问题的方法是跳过很多环节,以确保我们在启动时执行所有字符串转换(当我们还不需要实时时)。我确实认为有一种情况是我们将自己的转换器写入固定大小的堆栈分配数组。对于有问题的特定转换,我们可以依靠一些大小限制。
对于更通用的解决方案,您可以考虑编写自己的 ostringstream 版本,该版本使用固定大小的缓冲区(当然,对边界进行错误检查)。这将是一些工作,但如果你有很多这样的流操作,它可能是值得的。
std::ostringsteam
是一个方便的界面。它通过提供自定义链接 astd::string
到 a 。您可以实现自己的 std::streambuf。这使您可以进行整个内存管理。你仍然可以得到很好的格式,但是你可以完全控制内存管理。当然,结果是你得到你的格式化输出- 但如果你是一个嵌入式开发人员,这可能不是什么大问题。std::ostream
std::streambuf
std::ostream
char[]