C++为什么指向文件的流没有被填充?

6tr1vspr  于 2023-05-02  发布在  其他
关注(0)|答案(1)|浏览(93)

下面是在cpp preference网站上找到的代码。

#include <fstream>
#include <iomanip>
#include <iostream>
#include <string>
 
int main()
{
    std::ofstream os("test.txt");
    std::ifstream is("test.txt");
    std::string value("0");
 
    os << "Hello"; // clause 1
    is >> value;// clause 2
 
    std::cout << "Result before tie(): " << std::quoted(value) << "\n";
    is.clear();
    is.tie(&os);
 
    is >> value;
 
    std::cout << "Result after tie(): " << std::quoted(value) << "\n";
}

结果:
并列前的结果():“0”
并列后的结果():“你好”
问题:
我在第2条做了一个断点,注意到文件测试。txt未填充“hello”。
为什么?
谢谢

oxf4rvwz

oxf4rvwz1#

您对os的写入是buffered,不会立即刷新到磁盘。因此,从is进行的第一次读取尝试不会“看到”数据。
那么,为什么tie()调用可以解决这个问题呢?根据documentation of basic_ios::tie()
绑定流是与流缓冲区(rdbuf())控制的序列同步的输出流,即在*this上的任何输入/输出操作之前,在绑定流上调用flush()
所以在我们的例子中,对于is.tie(&os)调用,is是“*this”,os是“tied stream”。因此,该语句指示标准库在对is进行每次输入操作之前自动调用os.flush()
因此,在第二次读取is时,将数据写入磁盘的os.flush()首先被标准库隐式调用,这使得输入流可以读取数据。
您可以通过在子句1和2之间手动添加os.flush()Godbolt)来获得相同的结果并在第一次读取时接收数据:

os << "Hello"; // clause 1
    os.flush();
    is >> value;   // clause 2, value is "Hello" now!

但我应该注意,正如人们在评论中提到的那样,所有这些都很棘手,很容易导致难以掌握的代码。因此,通常应避免同时使用不同的句柄对同一文件进行阅读操作,除非绝对必要。

相关问题