天天看點

輸出緩沖區的管理

每個 IO 對象管理一個緩沖區,用于存儲程式讀寫的資料。如有下面語句:

系統将字元串字面值存儲在與流 os 關聯的緩沖區中。下面幾種情況将導緻緩沖區的内容被重新整理,即寫入到真實的輸出裝置或者檔案:

1. 程式正常結束。作為 main 傳回工作的一部分,将清空所有輸出緩沖區。

2. 在一些不确定的時候,緩沖區可能已經滿了,在這種情況下,緩沖區将會在寫下一個值之前重新整理。

3. 用操縱符(第 1.2.2 節)顯式地重新整理緩沖區,例如行結束符 endl。

4. 在每次輸出操作執行完後,用 unitbuf 操作符設定流的内部狀态,進而清空緩沖區。

5. 可将輸出流與輸入流關聯(tie)起來。在這種情況下,在讀輸入流時将重新整理其關聯的輸出緩沖區。

輸出緩沖區的重新整理

endl 操縱符,用于輸出一個換行符并重新整理緩沖區。

flush操縱符,用于重新整理流,但不在輸出中添加任何字元。

ends操縱符,這個操縱符在緩沖區中插入空字元 null,然後後重新整理它:

如果需要重新整理所有輸出,最好使用 unitbuf 操縱符。這個操縱符在每次執

行完寫操作後都重新整理流:

等價于:

nounitbuf 操縱符将流恢複為使用正常的、由系統管理的緩沖區重新整理方式。

如果程式不正常結束,輸出緩沖區将不會重新整理。在嘗試調試已崩潰的程式時,通常會根據最後的輸出找出程式發生錯誤的區域。如果崩潰出現在某個特定的輸出語句後面,則可知是在程式的這個位置之後出錯。

調試程式時,必須保證期待寫入的每個輸出都确實被重新整理了。因為系統不會在程式崩潰時自動重新整理緩沖區,這就可能出現這樣的情況:程式做了寫輸出的工作,但寫的内容并沒有顯示在标準輸出上,仍然存儲在輸出緩沖區中等待輸出。

如果需要使用最後的輸出給程式錯誤定位,則必須确定所有要輸出的都已經輸出。為了確定使用者看到程式實際上處理的所有輸出,最好的方法是保證所有的輸出操作都顯式地調用了 flush 或 endl。

如果僅因為緩沖區沒有重新整理,程式員将浪費大量的時間跟蹤調試并沒有執行的代碼。基于這個原因,輸出時應多使用 endl 而非 '\n'。使用endl 則不必擔心程式崩潰時輸出是否懸而未決(即還留在緩沖區,未輸出到裝置中)。

将輸入和輸出綁在一起

當輸入流與輸出流綁在一起時,任何讀輸入流的嘗試都将首先重新整理其輸出流關聯的緩沖區。标準庫将 cout 與 cin 綁在一起,是以語句:

導緻 cout 關聯的緩沖區被重新整理。

互動式系統通常應確定它們的輸入和輸出流是綁在一起的。這樣做意味着可以保證任何輸出,包括給使用者的提示,都在試圖讀之前輸出。

tie 函數可用 istream 或 ostream 對象調用,使用一個指向 ostream 對象的指針形參。調用 tie 函數時,将實參流綁在調用該函數的對象上。如果一個流調用 tie 函數将其本身綁在傳遞給 tie 的 ostream 實參對象上,則該流上的任何 IO 操作都會重新整理實參所關聯的緩沖區。

一個 ostream 對象每次隻能與一個 istream 對象綁在一起。如果在調用tie 函數時傳遞實參 0,則打破該流上已存在的捆綁。

繼續閱讀