繁体   English   中英

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

[英]Should std::endl always be used?

在本书C ++ Primer (第5版)的帮助下,我将从C跳入C ++,作者在其中指出:

程序员经常在调试过程中添加打印语句。 此类语句应始终刷新流。 否则,如果程序崩溃,则输出可能留在缓冲区中,从而导致有关程序崩溃位置的错误推断。

但是网上发布的建议则相反; 有人说不断刷新缓冲区对程序不利,并导致性能问题。

我的问题:

  1. 什么时候应该使用std::endl
  2. 作者是错误的还是我误解了他所说的内容?
  3. 您能否给出需要刷新输出流的任何现实情况?

聚苯乙烯

  1. 刷新缓冲区是什么意思?

调试输出应写入std::cerr ; 它是单位缓冲的,所以每个字符都会被刷新。 很少需要std::endl ,养成使用它的习惯会导致代码缓慢而神秘。 除非您知道需要刷新缓冲区,否则只需使用'\\n'即可。

点4和点3

从点4开始,因为其他所有内容都取决于它,而点3因为它紧密相关。

刷新流时,将获取流存储的所有数据并将其写入流所表示的基础介质中。

刷新后,它便已完成,提交并准备好供外界观察(或多或少。支持流的操作系统和硬件也可能会延迟写入,但是对此您无能为力) 。 在将其刷新之前,您无法阅读。 如果从未刷新过,则无法阅读。

问题是您不希望经常写IO,因为与CPU内部相比,从CPU中取出的所有内容花费的时间都不长。 有时会慢几万倍。 在CPU内部,有千兆赫兹和并行总线,一次可移动32位或更多位数据。 在外面,兆赫经常一次移动一点。

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

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

野蛮。 想象一下这样做几百或几千次以编写单个字符串。 但是,如果仅在字符串太大而无法保存或完成时才写字符串怎么办? 如果您写扇区而不是字节怎么办? 那你可以

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

一次可能对数千个字节进行一次操作。

点2

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

您以相对确定的速度交易程序,以确保您在需要查看重要消息时能够看到它。

点1

点1调用返回点std::endl既是行尾,又是刷新流的指令。 仅当需要行尾和冲洗时才少量使用它。 如果不需要冲洗,只需发送并在行尾添加'\\n'

接受Pete Becker的建议,并在可能的情况下使用std::cerr进行错误和调试。 这就是它的用途。 它依靠蛮力和无知运作。 这是痛苦的。 太慢了 而且它几乎总是有效。

作者和帖子都正确。

stream << std::endl实际上是stream << '\\n' << std::flush 显式刷新具有性能缺陷,这就是为什么您不应该在性能关键的情况下使用它。 你很少去想在调试这样微不足道的性能问题,所以它actualy 一个很好的做法,明确地冲洗调试输出。

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

当且仅当可以确定该流不引用交互式设备时,才完全缓冲。

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

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


关于您的实际问题:

两者都是正确的:

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

一旦添加“ always”,这只会成为问题。

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

当您刷新缓冲区时。

作者是错误的还是我想念他所说的内容的一部分?

我认为,就样式/设计/等而言,绝对量词(如“ always”,“ all”,“ never”等)应加一点盐。

(例外: 切勿调用未定义的行为。;-))

您能否给出实际的实际情况来冲洗输出流?

每当没有最新输出实际出现时,都是不可接受的。 在任何给定情况下是否都是这种情况,是一个判断电话。

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

1)什么时候应该使用std :: endl?

当您想要确保立即清除缓冲区时。

2)作者是错的还是我想念他所说的内容的一部分?

不,作者是正确的,你也是。

3)您能给出实际需要冲洗输出流的任何实际情况吗?

当particual字符串写入流很多次在很短的时间量std::endl确实造成性能损失因为不必要的冲洗可能缓冲每一次。 但是,当涉及仅出于调试目的而添加的打印行时,应始终刷新缓冲区。 再说一次,如果您仅使用打印行调试应用程序而没有使用调试器,则首先是在做错事。

您永远不要使用std::endl 这是一种必须消失的货运崇拜。 除了性能上的缺点外,什么都没有给您。 使其成为肌肉记忆:始终为"\\n" ,从不std::endl

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM