Pregunta

I'm using a small piece of code that generates PDF files, which I found on the internet, and tried to (softly) optimize it as the creation of a file would take ages. After profiling, I narrowed it down to the following piece of code :

std::ostringstream tmp;
tmp << std::hex << std::uppercase << std::setfill('0') <<
    std::setw(2) << r << " " <<
    std::setw(2) << g << " " <<
    std::setw(2) << b;

out << tmp.str();

found in a tight loop, with out being a ostringstream that contains basically the whole PDF content before it's written into the file. I found that tmp.str() was the line that took the most time in that loop, and saw when looking up the C++ reference that str() would return a copy of the stream's underlying string.

Then, I thought removing that copy and using directly out would be faster. So I dumped tmp and directly did:

out << std::hex << std::uppercase << std::setfill('0') <<
    std::setw(2) << r << " " <<
    std::setw(2) << g << " " <<
    std::setw(2) << b;

But now, the PDF file generated is considered "broken" and can't be opened by a PDF reader, while the previous one could be. I created a PDF with both methods (with the tmp stream and without) to compare the lines output, but found no obvious differences...

Then, what could be the reason for this ? Is there a reason to use that temporary stream ? Is it, and why could it be different than directly using the out stream ?

I thought it could be something related either to newlines or to the manipulators, but couldn't find anything significant on these

¿Fue útil?

Solución

The thing to consider is that the io manipulators (for example std::hex) are persistent from that point forward on the stream.

So once you insert the std::hex manipulator, all integral values are printed out in hex format from this point forward.

Your previous approach did not have this problem as the manipulator was on a transient stream. You could try inserting the std::dec manipulator once you are done...

Pulling up from Jan Hudec's comment, Boost IO State Savers are the nice way forward to handle this cleanly.

Otros consejos

Another little difference: If the formatted output to the std::ostringstream fails the destination out is not affected.

(Nim's answer describes the actual problem)

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top