流如何与另一个冲洗连接?

时间:2019-07-22 21:31:27

标签: c++ stream flush

我正在阅读C ++ Primer,第5版。当谈论冲洗流时,它说:

  

一个输出流可能绑定到另一个流。在这种情况下,   每当读取或写入绑定流时,都会刷新绑定流。通过   默认情况下,cin和cerr都与cout相关。因此,阅读cin或写信给   cerr刷新cout中的缓冲区。

我试图通过一个例子来理解这一点:

int main() {

    std::ofstream out("data.txt");
    std::ifstream in("data.txt");

    //in.tie(&out);// commenting this will print nothing

    out << "Hello there!";
    std::string str;
    while (in >> str)
        std::cout << str << " ";

    out.close();
    in.close();
}

正如您在上方看到的,输入和输出文件流对象inout使用相同的文件,因此输出打开文件“ data.txt”并向其中写入一些行,但保存它,输入流将尝试读取此未保存文件的内容。

  • 如果我将输入流对象in绑定到out,则可以正确获取内容。这是否意味着in强制out被刷新?

  • 如果我在in.tie(&out)行中注释掉了,那我使用的不是内容吗?

请向我解释一下它的工作原理。预先谢谢你。

1 个答案:

答案 0 :(得分:6)

关于缓冲I / O的事情是,您永远无法真正确定何时将缓冲区的内容刷新到外部序列。 iostream对象的内部缓冲区的大小是由实现定义的,它们可以决定在关闭或销毁流之前的任何时候刷新缓冲区(或不刷新缓冲区)。只有在关闭流(通过显式调用close()或生命周期结束)后才需要写入外部序列的流。这意味着输出操作 可以立即写入外部文件,也可以等待直到有更多内容流到缓冲区中。

您可以通过调用flush()方法显式刷新流,但是当您像std::cinstd::cout那样在输入和输出之间切换时,执行{{1 }}在每个输入操作之前(如果之前有写操作)。这是“绑定”流的来源。当您绑定输出流时,调用std::cout.flush()(在您的情况下为tie(),通常为in)中的流将调用{{1}在绑定流上执行的每个I / O操作之前。这样可以使两个流保持同步。

因此直接回答您的问题:

  

如果我将输入流对象std::cinflush()绑定在一起,则可以正确获取内容。这是否意味着in强制out被刷新了?

是的

  

如果我在in行中注释掉了,那我不使用out得到内容吗?

这取决于流如何管理缓冲区。执行输出的流可以立即执行写操作,或者可以在决定写操作之前等待缓冲区被进一步填充,或者可以等待其生命周期结束。此决定在iostream实现之间有所不同。