如何在 C++ 中对静态缓冲区执行字符串格式化?
How do I perform string formatting to a static buffer in C++?
我正在处理一段对性能要求很高的代码。我需要执行一些格式化的字符串操作,但我试图避免内存分配,即使是内部库。
在过去,我会做类似下面的事情(假设 C++11):
constexpr int BUFFER_SIZE = 200;
char buffer[BUFFER_SIZE];
int index = 0;
index += snprintf(&buffer[index], BUFFER_SIZE-index, "Part A: %d\n", intA);
index += snprintf(&buffer[index], BUFFER_SIZE-index, "Part B: %d\n", intB);
// etc.
我宁愿使用所有 C++ 方法(例如 ostringstream)来执行此操作,而不是使用旧的 C 函数。
我意识到我可以使用 std::string::reserve 和 std::ostringstream 来提前获得 space,但这仍然会执行至少一次分配。
有人有什么建议吗?
提前致谢。
Does anyone have any suggestions?
是的,使用 std::ostrstream。我知道它已被弃用。但我发现它对输出到静态缓冲区很有用。如果发生异常,则不会发生内存泄漏。
根本没有分配内存。
#include <strstream> // for std::ostrstream
#include <ostream> // for std::ends
// :
constexpr int BUFFER_SIZE = 200;
char buffer[BUFFER_SIZE];
std::ostrstream osout(buffer, sizeof(buffer));
osout << "Part A: " << intA << "Part B: " << intB << std::ends;
感谢所有发布的建议(甚至在评论中)。
我很欣赏 SJHowe 的建议,这是解决问题的最简单方法,但我希望通过这次尝试做的事情之一是开始为未来的 C++ 编码,而不是使用任何已弃用的东西。
我决定采用的解决方案源于 Remy Lebeau 的评论:
#include <iostream> // For std::ostream and std::streambuf
#include <cstring> // For std::memset
template <int bufferSize>
class FixedBuffer : public std::streambuf
{
public:
FixedBuffer()
: std::streambuf()
{
std::memset(buffer, 0, sizeof(buffer));
setp(buffer, &buffer[bufferSize-1]); // Remember the -1 to preserve the terminator.
setg(buffer, buffer, &buffer[bufferSize-1]); // Technically not necessary for an std::ostream.
}
std::string get() const
{
return buffer;
}
private:
char buffer[bufferSize];
};
//...
constexpr int BUFFER_SIZE = 200;
FixedBuffer<BUFFER_SIZE> buffer;
std::ostream ostr(&buffer);
ostr << "PartA: " << intA << std::endl << "PartB: " << intB << std::endl << std::ends;
我正在处理一段对性能要求很高的代码。我需要执行一些格式化的字符串操作,但我试图避免内存分配,即使是内部库。
在过去,我会做类似下面的事情(假设 C++11):
constexpr int BUFFER_SIZE = 200;
char buffer[BUFFER_SIZE];
int index = 0;
index += snprintf(&buffer[index], BUFFER_SIZE-index, "Part A: %d\n", intA);
index += snprintf(&buffer[index], BUFFER_SIZE-index, "Part B: %d\n", intB);
// etc.
我宁愿使用所有 C++ 方法(例如 ostringstream)来执行此操作,而不是使用旧的 C 函数。
我意识到我可以使用 std::string::reserve 和 std::ostringstream 来提前获得 space,但这仍然会执行至少一次分配。
有人有什么建议吗?
提前致谢。
Does anyone have any suggestions?
是的,使用 std::ostrstream。我知道它已被弃用。但我发现它对输出到静态缓冲区很有用。如果发生异常,则不会发生内存泄漏。 根本没有分配内存。
#include <strstream> // for std::ostrstream
#include <ostream> // for std::ends
// :
constexpr int BUFFER_SIZE = 200;
char buffer[BUFFER_SIZE];
std::ostrstream osout(buffer, sizeof(buffer));
osout << "Part A: " << intA << "Part B: " << intB << std::ends;
感谢所有发布的建议(甚至在评论中)。
我很欣赏 SJHowe 的建议,这是解决问题的最简单方法,但我希望通过这次尝试做的事情之一是开始为未来的 C++ 编码,而不是使用任何已弃用的东西。
我决定采用的解决方案源于 Remy Lebeau 的评论:
#include <iostream> // For std::ostream and std::streambuf
#include <cstring> // For std::memset
template <int bufferSize>
class FixedBuffer : public std::streambuf
{
public:
FixedBuffer()
: std::streambuf()
{
std::memset(buffer, 0, sizeof(buffer));
setp(buffer, &buffer[bufferSize-1]); // Remember the -1 to preserve the terminator.
setg(buffer, buffer, &buffer[bufferSize-1]); // Technically not necessary for an std::ostream.
}
std::string get() const
{
return buffer;
}
private:
char buffer[bufferSize];
};
//...
constexpr int BUFFER_SIZE = 200;
FixedBuffer<BUFFER_SIZE> buffer;
std::ostream ostr(&buffer);
ostr << "PartA: " << intA << std::endl << "PartB: " << intB << std::endl << std::ends;