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

前端 未结 4 1321
难免孤独
难免孤独 2020-12-13 06:16

In all examples that use some kind of buffering I see they use stream instead of string. How is std::ostringstream and << operator different than using string.append.

相关标签:
4条回答
  • 2020-12-13 06:33

    constructing a stream object is a significantly more complex operation than constructing a string object, because it has to hold (and, therefore, construct) its std::locale member, among other things needed to maintain state (but the locale is by a large margin the heaviest).

    Appending is similar: both maintain a contiguous array of characters, both allocate more when the capacity is exceeded. The only differences I can think of is that when appending to a stream, there is one virtual member function call per overflow (in addition to memory allocation/copying, which dominates overflow handling anyway), and operator<< has to do some extra checks of the stream state.

    Also, note that you're calling str(), which copies the entire string one more time, so based on what your code is written to do, the stream example does more and should be slower.

    Let's test:

    #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);
     }
    }
    

    that's 10 million repetitions

    On my Linux, I get

                       stream         string
    g++ 4.8          7.9 seconds      4.4 seconds
    clang++/libc++  11.3 seconds      3.3 seconds
    

    so, for this use case, in these two implementations, strings appear to work faster, but obviously both ways have a lot to improve (reserve() the string, move stream construction out of the loop, use a stream that doesn't require copying to access its buffer, etc)

    0 讨论(0)
  • 2020-12-13 06:42

    std::ostringstream is not necessarily stored as a sequential array of characters in memory. You would actually need to have continuous array of characters while sending those HTTP headers and that might copy/modify the internal buffer to make it sequential.

    std::string using appropriate std::string::reserve has no reason to act slower than std::ostringstream in this situation.

    However, std::ostringstream is probably faster for appending if you absolutely have no idea about the size you have to reserve. If you use std::string and your string grows, it eventually requires reallocation and copying of whole buffer. It would be better to use one std::ostringstream::str() to make the data sequential at once compared to multiple re-allocations that would happen otherwise.

    P.S. Pre-C++11 std::string is not required to be sequential either, whilst almost all libraries implement it as sequential. You could risk it or use std::vector<char> instead. You would need to use the following to do appending:

    char str[] = ";charset=";
    vector.insert(vector.end(), str, str + sizeof(str) - 1);
    

    std::vector<char> would be best for performance because it is most probably cheaper to construct, but it is probably not of importance compared to std::string and the actual time they take to construct. I have done something similar to what you are trying and went with std::vector<char> before. Purely because of logical reasons; vector seemed to fit the job better. You do not actually want string manipulations or such. Also, benchmarks I did later proved it to perform better or maybe it was only because I did not implement operations well enough with std::string.

    While choosing, the container that has requirements for your needs and minimal extra features usually does the job best.

    0 讨论(0)
  • 2020-12-13 06:43

    With stream you can have your class Myclass override the << operation so that you can write

    MyClass x;
    ostringstream y;
    y << x;
    

    For append you need to have a ToString method (or something similar) since you can't override the append function of string.

    For some code pieces use whatever you feel more comfortable with. Use stream for bigger projects where it's useful to be able to simply stream an object.

    0 讨论(0)
  • 2020-12-13 06:45

    If you concern about speed you should profile and/or test. In theory std::string::append should be not slower as it is simpler (stream has to deal with locale, different formatting and be more generic). But how faster one solution or another really is you can realize only by testing.

    0 讨论(0)
提交回复
热议问题