应该始终使用std :: endl吗?

psr*_*esh 6 c++

我在C++ Primer(第5版)一书的帮助下从C跳到C++,其中作者陈述如下:

程序员经常在调试期间添加print语句.此类语句应始终刷新流.否则,如果程序崩溃,输出可能会留在缓冲区中,从而导致程序崩溃的错误推断.

但网上帖子则另有说法; 有人说持续刷新缓冲区对程序不利并导致性能问题.

我的问题:

  1. 你应该什么时候使用std::endl
  2. 作者是错的还是我误解了他所说的任何部分?
  3. 您能否提供任何需要刷新输出流的真实场景?

PS

  1. 冲洗缓冲区意味着什么?

Pet*_*ker 9

应该将调试输出写入std::cerr; 它的单位是缓冲的,所以每个角色都会被冲洗掉.很少需要std::endl,并且养成使用它的习惯会导致代码神秘变慢.只是使用,'\n'除非你知道你需要刷新缓冲区.


use*_*301 6

第 4 点和第 3 点

从第 4 点开始,因为其他一切都取决于它,而从第 3 点开始,因为它紧密相关。

当您刷新流时,您将获取流存储的所有数据并将其写入由流表示的底层媒体。

当它被刷新时,它就完成了,提交并准备好被外界观察(或多或少。操作系统和支持流的硬件也可能会延迟写入,但你对此无能为力) . 在它被刷新之前你不能阅读它。如果它从来没有被冲洗过,你就无法阅读它。

问题是您不想经常写入 IO,因为与留在 CPU 内的相比,从 CPU 中流出的任何东西都需要花费大量的时间。有时慢数万倍。在 CPU 内部,您有千兆赫兹和并行总线一次移动 32 位或更多位的数据。在外面,你有兆赫兹经常一次移动一点。

以文件为例。不仅驱动器访问以 CPU 速度的一小部分运行,而且如果每个字节都直接传输到磁盘,那么对于每个字节,您可能必须

  1. 在磁盘上找到该字节的模拟。
  2. 将该字节周围的扇区加载到内存中。因此,您可能会移动数百或数千个字节,而不是移动一个字节。通常为 512 字节或 4096 字节。
  3. 将字节写入内存中的扇区
  4. 将内存中的扇区写回磁盘

野蛮。想象一下这样做几百或几千次来写一个字符串。但是,如果您只在字符串太大而无法容纳时才写入字符串,或者您已经完成了呢?如果你用扇区而不是字节来写怎么办?那么你可以

  1. 在磁盘上找到该字节的模拟扇区。
  2. 将存储的扇区写入磁盘

一次操作可能包含数千个字节。

第 2 点

第 2 点回到第 4/3 点,您无法阅读您不冲洗的内容。如果你想在屏幕上看到一个特定的输出并且你想现在看到它,你就刷新。如果您想在程序崩溃之前获得调试消息,并且可能在没有将最后几条绝对必要的消息显示在屏幕上的情况下终止,则刷新。历史上到处都是程序员在错误的地方寻找错误,因为他们没有得到最后几个未刷新的错误消息。

您交易程序速度是为了相对确定您会在需要查看重要消息时看到它。

第 1 点

点 1 回调到点 2。std::endl既是行尾,也是刷新流的指令。您可以谨慎使用它,并且仅当您需要行尾和冲洗时才使用它。如果您不需要刷新,只需发送和行尾:'\n'

std::cerr在可能的情况下,接受 Pete Becker 的建议并用于错误和调试。这就是它的建造目的。它靠蛮力和无知运作。这是痛苦的。它很慢。它几乎总是有效。


Dev*_*lar 5

默认情况下std::cout链接到stdout,这是...

当且仅当可以确定流不涉及交互设备时才完全缓冲。

(C99,7.19.3 文件,第 7 段。)

这意味着,如果您的输出发送到终端,std::endl则 vs."\n"首先没有区别。;-)


关于您的实际问题:

两者都是正确的:

  • 未刷新的输出缓冲区可能会导致对程序崩溃位置的错误推断
  • 刷新输出缓冲区会影响性能

只有添加“始终”后,这才会成为问题。

你应该什么时候使用std::endl

当你刷新缓冲区时。

作者是错的还是我没有理解他所说的任何部分?

我认为就风格/设计等而言,应该对“总是”、“全部”、“从不”等绝对量词持保留态度。

(例外:永远不要调用未定义的行为。;-))

您能否给出任何实际需要刷新输出流的真实场景?

每当没有实际出现最新输出时都是不可接受的。在任何给定场景中是否都是这种情况需要判断。

就我个人而言,我认为生产/事务日志比调试日志重要......