簡體   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