[英]How the buffer of cout work?
幾天前我知道cout有緩沖區,當我google它時,據說緩沖區有點像堆棧,從右到左獲取cout的output和printf,然后將它們輸出(到控制台或文件) 從上到下。 像這樣,
a = 1; b = 2; c = 3;
cout<<a<<b<<c<<endl;
buffer:|3|2|1|<- (take “<-” as a poniter)
output:|3|2|<- (output 1)
|3|<- (output 2)
|<- (output 3)
然后我在下面寫一個代碼,
#include <iostream>
using namespace std;
int c = 6;
int f()
{
c+=1;
return c;
}
int main()
{
int i = 0;
cout <<"i="<<i<<" i++="<<i++<<" i--="<<i--<<endl;
i = 0;
printf("i=%d i++=%d i--=%d\n" , i , i++ ,i-- );
cout<<f()<<" "<<f()<<" "<<f()<<endl;
c = 6;
printf("%d %d %d\n" , f() , f() ,f() );
system("pause");
return 0;
}
VS2005下output為
i=0 i++=-1 i--=0
i=0 i++=-1 i--=0
9 8 7
9 8 7
看來stack的方式是對的~不過,我昨天看了C++ Primer Plus,據說cout從左到右工作,每次返回一個對象(cout),所以“這就是讓你連接output的功能通過使用插入”。 但是從左到右的方式不能解釋 cout<
然后Alnitak告訴我,“<< 運算符實際上是 ostream& operator<<(ostream& os, int),所以另一種寫法是: operator<< ( operator<< ( operator<< ( cout, a ), b ), c )",
如果最正確的論點首先被評估,它可以得到一些解釋。
現在我對 cout 的緩沖區如何工作感到困惑,有人可以幫助我嗎?
你混合了很多東西。 迄今為止:
cout
的實現細節嘗試分別閱讀它們。 並且不要在一個 go 中考慮所有這些。
printf("i=%d i++=%d i--=%d\n", i, i++,i-- );
上面的行調用了未定義的行為。 閱讀常見問題解答3.2 。 請注意,您觀察到的是函數調用約定的副作用以及特定實現(即您的實現)在堆棧中傳遞參數的方式。 如果您在其他機器上工作,則不能保證相同。
我認為您將 function 調用的順序與緩沖混淆了。 當您有一個cout
語句后跟多個插入<<
您實際上是在調用多個 function 調用,一個接一個。 所以,如果你要寫:
cout << 42 << 0;
這真的意味着:你打電話,
cout = operator<<(cout, 42)
然后在對同一運算符的另一個調用中使用 return:
cout = operator<<(cout, 0)
您通過上述測試的內容不會告訴您任何cout
的內部表示。 我建議您查看 header 文件以了解更多信息。
就像一般提示一樣,永遠不要在同一行中使用 i++ 作為 i 或 i-- 的另一個用法。
The issue is that function arguments can be evaluated in any order, so if your function arguments have any side-effects (such as the increment and decrement operations) you can't guarantee that they will operate in the order you expect. 這是要避免的。
這種情況也是如此,這類似於您的 cout 使用的實際擴展:
函數1(函數2(foo),bar);
編譯器可以在調用 function2 之前自由評估 bar,反之亦然。 例如,您可以保證 function2 在調用 function1 之前返回,但不能保證它們的 arguments 會按特定順序進行評估。
當您執行以下操作時,這會成為一個問題:
函數1(函數2(i++),i);
您無法指定是否在“i++”之前或之后評估“i”,因此您可能會得到與預期不同的結果,或者不同編譯器甚至相同編譯器的不同版本的不同結果.
底線,避免有副作用的陳述。 僅當它們是該行中唯一的語句或者您知道您只修改同一個變量一次時才使用它們。 (“行”表示單個語句加上分號。)
您看到的是未定義的行為。
局部i
和全局c
在沒有序列點的情況下多次加/減。 這意味着您獲得的價值可以是任何東西。 取決於編譯器,可能還取決於處理器架構和內核數量。
cout
緩沖區可以被認為是隊列,所以 Alnitak 是對的。
除了正確指出您看到未定義行為的其他答案之外,我想我會提到std::cout
使用std::streambuf
類型的 object 進行內部緩沖。 基本上它是一個抽象的 class 代表緩沖區(大小特定於實現,對於無緩沖 stream 緩沖區甚至可以為 0)。 std::cout
的一個寫成這樣,當它“溢出”時,它會被刷新到 stdout。
實際上,您可以更改與std::cout
關聯的std::streambuf
(或任何 stream )。 如果您想做一些聰明的事情,例如使所有std::cout
調用以日志文件或其他內容結尾,這通常很有用。
正如您所說的那樣,您將調用約定與其他細節混淆了,它們與 std::cout 的緩沖完全無關。
此外,混合 output 范例(printf 和 cout)是特定於實現的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.