15

我正在阅读关于 I/O 的 cplusplus.com 教程。最后,它说 fstream 缓冲区与磁盘上的文件同步

显式地,使用操纵器:当在流上使用某些操纵器时,会发生显式同步。这些操纵器是:flush 和 endl。

明确地,使用成员函数sync():调用不带参数的流的成员函数sync() 会导致立即同步。如果流没有关联的缓冲区或发生故障,此函数返回一个等于 -1 的 int 值。否则(如果流缓冲区已成功同步),则返回 0。

除了一些其他隐式情况(例如破坏和 stream.close() )

调用 fstream::flush() 和 fstream::sync() 有什么区别?结束?

在我的代码中,我一直使用flush()。

关于 std::flush() 的文档:

刷新流缓冲区

将与流关联的缓冲区同步到其受控的输出序列。这实际上意味着缓冲区中的所有未写入字符都将尽快写入其受控输出序列(“刷新”)。

关于 std::streambuf::sync() 的文档:

将输入缓冲区与字符源同步

调用它以将流缓冲区与受控序列(如文件流中的文件)同步。公共成员函数 pubsync 调用这个受保护的成员函数来执行这个动作。

如果这是一个新手问题,请原谅我;我是菜鸟。

4

4 回答 4

15

basic_ostream::flush 这是一个非虚拟函数,它将未提交的更改写入底层缓冲区。如果发生错误,它会在使用的流对象中设置一个错误标志。这是因为返回值是对流本身的引用,以允许链接。

basic_filebuf::sync 这是一个函数,它将所有挂起的更改写入底层文件并返回错误代码以表示成功或失败。

endl 这在应用于 an 时ostream,将 an 写入'\n'流,然后调用flush该流。

所以,本质上:flush是任何流的更通用的函数,而sync显式绑定到文件。flush是非虚拟的,而是sync虚拟的。这改变了在继承的情况下如何通过指针(指向基类)使用它们。此外,它们在报告错误的方式上有所不同。

于 2013-01-10T06:35:59.783 回答
6

syncinput流的成员,所有未读字符都会从缓冲区中清除。flushoutput流的成员,缓冲的输出被传递给内核。

于 2013-01-10T06:27:15.303 回答
4

C++ I/O 涉及多个类之间的协作:streambufferlocalelocale::facet -s。

特别是syncand是andflush中都存在的成员函数,因此请注意您所指的文档,因为它们做不同的事情。streamstreambuf

On streams flush告诉流告诉缓冲区(注意重定向)将其内容刷新到目标。这确保没有“挂起的写入”剩余。

std::endl, 当应用于thestreamwith时<<, 不超过一个

thestream.put('\n'); thestream.flush();

始终在上,sync告诉告诉缓冲区刷新内容(用于输出)并尽可能多地读取(用于输入)以重新填充缓冲区

请注意,-in buffers -sync 也可以在内部调用overflow以处理“缓冲区已满”(用于输出)和“缓冲区空”(用于输入)情况。

因此,我感觉,sync它更像是流中用于缓冲通信和缓冲区实现的“内部”函数(它是虚拟的并且在不同的缓冲区类型中被覆盖),而flush更像是流和客户端程序之间的接口。

endl...只是一个捷径。

于 2013-01-10T07:26:39.857 回答
1

我的理解如下:

flush()会将数据从库缓冲区中取出到操作系统的写入缓冲区中,并最终导致完全同步(数据被完全写出),但同步完成时肯定取决于操作系统。

sync()将在给定的操作系统中尽可能地尝试强制实现完全同步 - 但所涉及的操作系统可能会或可能不会促进这一点。

所以flush()是:将数据从缓冲区中取出并排队写入。
sync()是:如果可能,现在强制将数据明确写出。

这是我对此的理解,但当我想起来时,我不记得我是如何理解的,所以我也很想听听其他人的意见。

于 2013-01-10T06:24:59.177 回答