【问题标题】:make the compiler not to automatically flush the buffer使编译器不自动刷新缓冲区
【发布时间】:2013-07-31 18:03:55
【问题描述】:

为什么下面的代码没有阻止编译器自动刷新缓冲区?

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

输出:

helloworld

我正在使用 Visual Studio 2012 Ultimate

【问题讨论】:

  • 流可以随时清除角色。
  • @DanielKO 但在任何合理的实现中,它都不会。它只会在请求时或缓冲区已满时刷新。我无法想象他的文字会填满缓冲区。 (另一方面,默认情况下,当您从std::cin 输入时,它将刷新std::cout。)
  • @James Kanze cout 可以是任何具体类型,只要它继承自 std::ostream。它可以为所欲为,甚至可以通过 fprintf() 进行打印,这是一个很好的工具。例如,libstdc++ 使用 __gnu_cxx::stdio_filebuf 实现 cout。不使用 fprintf,而是使用 fwrite。同样的事情。
  • @DanielKO 当然。一个实现也可以为每个字符输出休眠 5 秒,并且仍然保持一致。还有 QoI 考虑因素。一个人有一定的期望,至少在某些系统上是这样;从质量的角度来看,系统应该满足这些要求。而且大多数系统确实在特定点上以某种方式失败。

标签: c++ visual-studio visual-c++ visual-studio-2012


【解决方案1】:

AFAIK,只要实现喜欢这样做,就可以刷新流,即不能保证在插入操作后会刷新流。但是,您可以使用这些操纵器之一来确保您的流被刷新(我知道这些是唯一的,所以如果有人知道其他人,请发表评论):

【讨论】:

  • 本质上只能强制刷新;你不能强迫它不冲洗。
  • 通过说stream,你说的是cin的流还是标准库中所有可能的IO流,比如内存中字符串 IO?
  • @atoi.powered 在内存中的字符串 IO 中,flush 很容易成为空操作。但该标准确实允许实现随时调用它。
【解决方案2】:

该标准允许实现随时刷新 喜欢它,但从实施质量的角度来看,一个 真的没想到这里会出现同花顺。您可以尝试添加 一个setbuf,告诉std::cin使用你指定的缓冲区:

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

同样,该标准并不能保证任何事情,但如果这不是 尊重,我认为质量差到足以保证一个错误 报告。

最后,如果情况变得更糟,您可以随时插入 一个过滤streambuf,它执行你想要的缓冲。你 不应该这样做,但这不会是我们第一次不得不这样做 编写额外的代码来解决编译器质量不足的问题 或图书馆。如果您所做的只是简单的输出(不 寻求或任何类似以下的东西应该做 技巧:

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

那就这样吧:

BufferingOutStreambuf buffer( std::cout );

作为main 的第一行。 (有人可能会说 iostreams 应该从一开始就设计成这样工作, 过滤 streambuf 以缓冲 代码翻译。但 不是,而且这个不应该对于一个体面的人来说是必要的 实施。)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-06-18
    • 2018-07-03
    • 1970-01-01
    • 1970-01-01
    • 2021-09-03
    • 2018-07-11
    • 1970-01-01
    • 2020-04-06
    相关资源
    最近更新 更多