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
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
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.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
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.)