Search code examples
c++stringperformanceostringstream

How do I perform string formatting to a static buffer in C++?


I am working in a section of code with very high performance requirements. I need to perform some formatted string operations, but I am trying to avoid memory allocations, even internal library ones.

In the past, I would have done something similar to the following (assuming 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.

I would prefer to use all C++ methods, such as ostringstream, to do this instead of the old C functions.

I realize I could use std::string::reserve and std::ostringstream to procure space ahead of time, but that will still perform at least one allocation.

Does anyone have any suggestions?

Thanks ahead of time.


Solution

  • My thanks to all that posted suggestions (even in the comments).

    I appreciate the suggestion by SJHowe, being the briefest solution to the problem, but one of the things I am looking to do with this attempt is to start coding for the C++ of the future, and not use anything deprecated.

    The solution I decided to go with stems from the comment by 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;