1

Why does the below code not stop the compiler from flushing the buffer automatically?

cout.sync_with_stdio(false);
cin.tie(nullptr);
cout << "hello";
cout << "world";
int a;
cin >> a;

output:

helloworld

I'm using Visual Studio 2012 Ultimate

aaronman
  • 18,343
  • 7
  • 63
  • 78
atoipowered
  • 506
  • 4
  • 16
  • [Relevant comment](http://stackoverflow.com/questions/213907/c-stdendl-vs-n#comment6217683_214076) – Bartek Banachewicz Jul 31 '13 at 18:13
  • The stream can flush out the character whenever it feels like doing so. – DanielKO Jul 31 '13 at 18:38
  • @DanielKO But in any reasonable implementation, it won't. It will only flush when requested, or when the buffer is full. And I can't imagine his text filling the buffer. (On the other hand, by default, when you input from `std::cin`, it will flush `std::cout`.) – James Kanze Jul 31 '13 at 18:46
  • @James Kanze Why? If I spent some good amount of time optimizing fprintf, I might as well use its internal buffering instead of having another buffer on top. Why would that be unreasonable? – DanielKO Jul 31 '13 at 18:49
  • @DanielKO Why would `std::ostream` have anything to do with `fprintf`? That would just slow it down, by adding yet another layer of indirection. – James Kanze Jul 31 '13 at 18:55
  • 1
    @James Kanze cout can be of any concrete type, as long as it inherits from std::ostream. It can do whatever it wants, even print through fprintf(), which is a great tool for the job. For example, libstdc++ implements cout using __gnu_cxx::stdio_filebuf. Not using fprintf, but fwrite. Same thing. – DanielKO Jul 31 '13 at 19:14
  • @JamesKanze: I recall stepping into MSVC's ostream< – Mooing Duck Jul 31 '13 at 22:39
  • 2
    @DanielKO Of course. An implementation could also sleep for 5 seconds for each character output, and still be conform. There's also QoI considerations. One has certain expectations, at least on certain systems; systems should meet them, from a quality point of view. And most systems do fail in one way or another, on specific points. – James Kanze Aug 01 '13 at 08:28
  • @JamesKanze I'm not sure what you are arguing... a good implementation should use straight syscalls to avoid using stdio functions? MS and libstdcxx (used by clang) do it this way too. – DanielKO Aug 01 '13 at 19:31
  • @DanielKO A good implementation will either use system calls directly (if it isn't trying to be portable), or will use `fwrite` or something similar, which still leaves the buffering up to `std::ostream`. If you're familiar with the interface to `std::streambuf`, this is obvious. – James Kanze Aug 02 '13 at 08:08

2 Answers2

4

AFAIK, the stream can be flushed whenever the implementation likes to do so, i.e. there's no guarantee that the stream will be flushed after an insert operation. However, you could use one of these manipulators to ensure your stream gets flushed (these are the only ones I know of so if someone is aware of others, please comment):

  • std::endl - inserts a newline into the stream and flushes it,
  • std::flush - just flushes the stream,
  • std::(no)unitbuf - enables/disables flushing the stream after each insert operation.
Tuntuni
  • 481
  • 1
  • 7
  • 19
  • 1
    Essentially, you can only force it to flush; you can't force it to not flush. – DanielKO Jul 31 '13 at 19:15
  • By saying stream, are you talking about the cin's stream or every possible IO stream in the standard library, such as in-memory string IO? – atoipowered Jul 31 '13 at 23:38
  • @atoi.powered In an in-memory string IO, flush could easily be a no-op. But the standard does allow an implementation to call it whenever it wants. – James Kanze Aug 01 '13 at 08:55
1

The standard allows an implementation to flush any time it feels like it, but from a quality of implementation point of view, one really doesn't expect a flush here. You might try adding a setbuf, telling std::cin to use a buffer you specify:

std::cout.rdbuf()->setbuf( buffer, sizeof(buffer) );

Again,the standard doesn't guarantee anything, but if this isn't respected, I'd consider the quality bad enough to warrant a bug report.

Finally, if worse comes to worse, you can always insert a filtering streambuf which does the buffering you want. You shouldn't have to, but it won't be the first time we've had to write extra code to work around a lack of quality in compilers or libraries. If all you're doing is straightforward output (no seeks, or anything, something like the following should do the trick:

class BufferingOutStreambuf : public std::streambuf
{
    std::streambuf* myDest;
    std::ostream* myOwner;
    std::vector<char> myBuffer;

    static size_t const bufferSize = 1000;
protected:
    virtual int underflow( int ch )
    {
        return sync() == -1 
            ? EOF
            : sputc( ch );
    }
    virtual int sync()
    {
        int results = 0;
        if ( pptr() != pbase() ) {
            if ( myDest->sputn( pbase(), pptr() - pbase() )
                    != pptr() - pbase() ) {
                results = -1;
            }
        }
        setp( &myBuffer[0], &myBuffer[0] + myBuffer.size() );
        return results;
    }
public:
    BufferingOutStreambuf( std::streambuf* dest )
        : myDest( dest )
        , myOwner( NULL )
        , myBuffer( bufferSize )
    {
        setp( &myBuffer[0], &myBuffer[0] + myBuffer.size() );
    }

    BufferingOutStreambuf( std::ostream& dest )
        : myDest( dest.rdbuf() )
        , myOwner( &dest )
        , myBuffer( bufferSize )
    {
        setp( &myBuffer[0], &myBuffer[0] + myBuffer.size() );
        myOwner->rdbuf( this );
    }

    ~BufferingOutStreambuf()
    {
        if ( myOwner != NULL ) {
            myOwner->rdbuf( myDest );
        }
    }
};

Then just do:

BufferingOutStreambuf buffer( std::cout );

as the first line in main. (One could argue that iostreams should have been designed to work like this from the start, with filtering streambuf for buffering and code translation. But it wasn't, and this shouldn't be necessary with a decent implementation.)

James Kanze
  • 150,581
  • 18
  • 184
  • 329