1. 程式人生 > >C++中重新整理輸出緩衝區

C++中重新整理輸出緩衝區

每一個輸出流都管理一個緩衝區,用來儲存程式讀寫的資料。因此要將資料真正寫到輸出裝置中,就需要重新整理緩衝區。導致緩衝區重新整理的原因大體有以下5種。

1、程式正常結束,作為main函式return操作的一部分,緩衝區被重新整理。

2、當緩衝區滿了的時候,會重新整理緩衝區。

3、可以使用操作符endl、flush和ends來顯示的重新整理緩衝區。這三個都是IO庫中的操作符,endl能完成換行和重新整理緩衝區的工作。flush只完成重新整理緩衝區的工作。而ends會向緩衝區插入一個空字元,然後重新整理緩衝區。例子如下:

#include <algorithm>
#include <string>
#include <iterator>

using namespace std;

int main()
{
	cout << "hi" << endl;
	cout << "hi" << flush;
	cout << "hi" << ends;
        cout << "hi";

	system("pause");
	return 0;
}

編譯結果如下:

如上所述,ends向緩衝區插入了一個空格。我們可以觀察到,例子中最後一句並沒有使用任何操作符重新整理緩衝區,但是依舊將緩衝區的內容輸出出來了。顯然不可能是因為輸出緩衝區滿了的緣故,程式也沒有結束。這是因為當系統比較空閒的時候,會檢視緩衝區的內容,如果發現有新的內容,系統就會將緩衝區的內容輸出出來。不過這種重新整理是不可靠的,完全取決於系統的狀態,因此,我們最好使用上面的操作符來顯示重新整理緩衝區。

4、在每個輸出操作之後,我們可以用操作符unitbuf設定流的內部狀態,來清空緩衝區。設定了unitbuf操作符之後,在對緩衝區的每一次寫操作之後都會進行一次flush操作。相應的,可以設定nounitbuf操作符,使該輸出流恢復使用正常的系統管理的緩衝區重新整理機制。預設情況下,cerr流物件是已經設定了unitbuf的,因此每次寫到cerr的內容都會立即重新整理。設定unitbuf和nounitbuf的方法如下:

            cout << unitbuf;      //所有的輸出操作後都會立即重新整理緩衝區

            cout << nounitbuf;    //回到正常的緩衝方式

5、一個輸出流可能被關聯到另一個流。在這種情況下,當讀寫被關聯的流時,關聯到的流緩衝區會被重新整理。預設情況下,cin和cerr都關聯到cout。因此,讀cin或寫cerr都會導致cout的緩衝區被重新整理。關聯兩個流可以使用tie函式,其有兩個版本:

      1)不帶引數,返回指向輸出流的指標。如果本物件當前關聯到一個輸出流,則返回的就是指向這個流的指標。如果該物件沒有關聯到流,則返回空指標。

      2)接受一個指向ostream的指標,將自己關聯到此ostream。

注意:每個流同時最多關聯到一個流,但多個流可以同時關聯到同一個ostream。

 

最後,我們在除錯程式的時候要記住:程式出現異常終止的時候,輸出緩衝區是不會重新整理的(這和程式正常執行結束不一樣)。也就是說資料很可能還在緩衝區中,沒有輸出出來。