我借助于 C ++ Primer (第5版)这本书从C跳到C ++,其中作者声明如下:
程序员经常在调试期间添加print语句。这样 语句应始终刷新流。否则,如果是程序 崩溃,输出可能会留在缓冲区,导致错误 关于程序崩溃的地方的推论。
但网上帖子另有说法;有人说持续刷新缓冲区对程序有害并导致性能问题。
我的问题:
std::endl
? P.S。
答案 0 :(得分:9)
调试输出应写入std::cerr
;它的单位是缓冲的,所以每个角色都会被冲洗掉。很少需要std::endl
,养成使用它的习惯会导致代码神秘变慢。只需使用'\n'
,除非您知道需要刷新缓冲区。
答案 1 :(得分:2)
从第4点开始,因为其他一切都取决于它,而第3点因为它紧密相关。
当您刷新流时,您将获取流存储的所有数据并将其写入流所代表的基础媒体。
当它被刷新时,它被完成,提交并准备好被外界观察(或多或少。操作系统和支持流的硬件也可能会延迟写入,但是你不是很多可以做到这一点)。在刷新之前,您无法读取它。如果它从未被刷新,你就无法阅读它。
问题是你不想经常写入IO,因为任何离开CPU的东西都会花费不计其数的时间。有时会慢几万倍。在CPU内部,您可以使用千兆赫和并行总线一次移动数据32位或更多位。外面你有兆赫经常一次移动一个位。
将文件作为经典示例。驱动器访问不仅以CPU的速度的一小部分运行,而且如果每个字节直接进入磁盘,那么对于每个字节,您可能必须
野蛮。想象一下这样做几百或几千次来写一个字符串。但是如果你只是在字符串太大而无法容纳或者你已经完成时写了怎么办?如果你用扇区写而不是字节怎么办?那么你可以
一次性可能有数千个字节的一次操作。
第2点可以追溯到第4点/第3点,你无法阅读你不会冲洗的内容。如果你想在屏幕上看到一个特定的输出,你想现在看到它,你就会冲洗。如果你想在程序崩溃之前收到一条调试消息,并且很可能在没有将最后几条绝对必要的消息放到屏幕上的情况下终止,你就会刷新。历史上充满了程序员在错误的位置查找错误,因为他们没有得到最后几个未刷新的错误消息。
您正在交易程序速度,以确保在需要查看时会看到重要信息。
第1点回调到第2点。std::endl
既是行尾,也是刷新流的指令。只有当你需要一个行尾和一个同花时,你才能谨慎使用它。如果您不需要同花,只需发送和结束行:'\n'
。
采取Pete Becker的建议并尽可能使用std::cerr
进行错误和调试。这就是为它而建的。它以蛮力和无知运作。这很痛苦。它很慢。它几乎总是有效。
答案 2 :(得分:1)
作者和帖子都是对的。
stream << std::endl
实际上是stream << '\n' << std::flush
。显式刷新具有性能缺陷,这就是为什么不应该在性能关键的情况下使用它。在调试时,您很少考虑这种可忽略的性能问题,因此它实际上 是显式刷新调试输出的好方法。
答案 3 :(得分:0)
默认情况下,std::cout
与stdout
相关联,即......
当且仅当可以确定流不被引用时,完全缓冲 到交互设备。
(C99,7.19.3档案,第7段。)
这意味着,如果您的输出发送到终端, std::endl
与"\n"
首先没有区别。; - )
关于你的实际问题:
两者都是如此:
只有在您添加&#34;始终&#34;
后,这才会成为问题什么时候应该使用
std::endl
?
当希望刷新缓冲区时。
作者是错的还是我错过了解他所说的任何部分?
我认为绝对量词如&#34;总是&#34;,&#34;所有&#34;,&#34;从不&#34;就样式/设计/等而言,应该采用一粒盐。
(例外:从不调用未定义的行为。;-))
您是否可以根据实际需要提供任何真实场景来刷新输出流?
每当没有最新的输出实际出现时是不可接受的。在任何给定情况下是否都是这种情况是判断。
就个人而言,我认为生产/交易日志比调试日志更多更重要...
答案 4 :(得分:0)
1)什么时候应该使用std :: endl?
如果要确保立即刷新缓冲区。
2)作者是错的还是我错过了解他的任何部分 说明
不,作者是正确的,你也是。
3)你能给出真正需要冲洗的现实场景吗? 输出流?
如果在短时间内将特定字符串写入流中很多次std::endl
可能确实会导致性能下降,因为每次都会不必要地刷新缓冲区。但是,当涉及为了调试而单独添加的打印行时,应始终刷新缓冲区。再说一次,如果你在没有使用调试器的情况下调试只有打印行的应用程序,那么你首先会做错事。
答案 5 :(得分:-8)
你永远不应该使用std::endl
。这是一种必须消失的货物崇拜。给你带来性能上的缺点。只需使它成为肌肉记忆:始终"\n"
,永远不会std::endl
。