std::endl << std::flush有什么作用?

12

我正在查看的旧代码中,std::endl 后面紧跟着 std::flush 的情况非常普遍。一开始,我认为这是多余的,因为我在以下链接描述的 std::endlstd::flush 中看到了:

http://zh.cppreference.com/w/cpp/io/manip/endl

http://zh.cppreference.com/w/cpp/io/manip/flush

以下是我在旧源代码中看到的示例:

std::cout << "Generic Notification" << std::endl << std::flush;

然而,许多资深软件开发人员在这些年中已经看过这段代码,我想知道是否有一些细节我错过了。在std::endl之后使用std::flush是否有任何用处?


1
如果不是 std::cout 而是其他流,可能有原因... - 463035818_is_not_a_number
4
那会是什么呢?std::endl被定义为“换行并刷新缓冲区”。 - Angew is no longer proud of SO
1
@Angew 我刚才考虑了一下,OP可能为了创建一个mcve而将原始代码中的任何流替换为std::cout。当然,即使对于类似于自定义流的对象,在那个位置使用flush也没有任何用处。 - 463035818_is_not_a_number
2
我第一条评论更加精确:如果不是标准流,可能有原因需要使用 flush,但这仍然不是一个好的理由,因为在 endl 上不刷新的流可以被认为是损坏的。 - 463035818_is_not_a_number
5
也许没有人有胆量告诉那些年长者这没有任何意义 ;) - 463035818_is_not_a_number
显示剩余5条评论
3个回答

17

这没有任何意义。

如果我必须猜测为什么你的遗留代码包含这些行,有几种可能性,首先是(我认为)最有可能发生的情况:

  • 某人错误地添加了对std::flush的显式调用,而高级开发人员并未认为需要修复此问题
  • 该代码源自C++标准广泛采用之前的某个时期,在那个时期,本地编译器实现的std::endl不会触发刷新,这意味着您的高级开发人员(正确地)理解需要刷新
  • 旧版本的C++标准可能不要求std::endl触发刷新
  • 您的高级开发人员对std::endl的行为存在误解。
  • 您的执行环境是一个奇怪的庞然大物,实际上需要将输出刷新两次才能预期得到所需结果。

6
在源代码中执行文本搜索和替换时,也会出现诸如这样的愚蠢问题,例如:将<< '\n'替换为<< std::endl - Drew Dormann
2
很好的回答,但是“C++标准的旧版本…” - 不,C++98是第一个标准,它确实需要flush。最多,一些早期版本的标准库可能会有所不同,尽管我怀疑这一点。顺便说一句,我可以想到一个原因,为什么他们会使用endl而不是'\n',尽管他们没有意识到它会刷新缓冲区,那就是系统没有LF行终止符(最有可能是Windows)。当然,在cout/cerr或文本模式的ofstream上并不需要这样做,再次强调,即使对于二进制的ofstreamendl也没有帮助,但这可能是错误的推理。 - Arne Vogel
我特别喜欢最后一个场景。 - Kaiserludi

8
我会补充其他有效答案,经常情况下,std::flushstd::endl都没有很好的用途。基本上,std::endl = 开始新行 + 刷新流。然而,很多人倾向于以std::endl结束他们的行,因为这“听起来对了”- 结束该行。但实际上我们很少需要刷新输出流。有时我们确实需要(例如当我们期望用户回复字符串或者重要性能监控),但这只是例外,而不是规则。因此,可能需要一点时间来适应,但我们真正默认的方式应该是:
std::cout << bunch_of_stuff << '\n';

就是这样了!


是的!如果您需要将输出刷新到终端,请使用std::cerr - Brent Bradburn
在测试/调试时,清空输出很方便。 - gast128

5
在符合标准的环境下,这段代码中的std::flush没有任何有用的作用。
写这段代码的人要么没有完全理解std::endl的语义,要么是为了绕过编译器或执行环境的某些限制。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接