make the compiler not to automatically flush the buffer

倾然丶 夕夏残阳落幕 提交于 2019-12-24 12:09:09

问题


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


回答1:


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.



回答2:


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



来源:https://stackoverflow.com/questions/17977657/make-the-compiler-not-to-automatically-flush-the-buffer

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!