一个流是如何与另一个流联系在一起的?

How is a stream tied to another flushed?

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

An output stream might be tied to another stream. In this case, the buffer of the tied stream is flushed whenever the tied stream is read or written. By default, cin and cerr are both tied to cout. Hence, reading cin or writing to cerr flushes the buffer in 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" 并向其中写入一些行但不保存它,输入流尝试读取这个未保存文件的内容。

请向我解释一下它是如何工作的。提前谢谢你。

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

您可以通过调用 flush() 方法显式刷新流,但是当您像使用 std::cinstd::cout 那样在输入和输出之间切换时,这样做会变得乏味 std::cout.flush() 在每次输入操作之前(如果之前有写)。这就是 "tying" 流的用武之地。当您绑定输出流时,调用 tie() 的流(在您的情况下为 in,通常为 std::cin)调用 flush() 在绑定流上执行的每个 I/O 操作之前。这允许两个流保持同步。

所以直接回答你的问题:

If I tie the input stream object in with out then I get the content correctly. Does this mean in forces out to be flushed?

是的。

If I comment out the line in.tie(&out) then I don't get the content using in?

这取决于流如何管理缓冲区。执行输出的流可以立即执行写入,或者它可以等待其缓冲区被进一步填充后再决定写入,或者它可以等到其生命周期结束。此决定因 iostream 实现而异。