2017-12-27 289 views
1

我經歷了幾個有關std :: cout評估順序的問題,並且我明白std :: cout的參數之間沒有順序點,但是我無法理解下面的代碼是如何工作的:C++:cout和函數調用之間的評估順序

saved_fd = dup(STDOUT_FILENO); 
std::cout << "Redirecting std out to /dev/null"; 
redirect_stdout() 
<do some stuff> 
std::cout << "Restoring std out back to standard output"; 
restore_stdout(); 

我的功能redirect_stdout()和restore_stdout(),使用DUP2調用將標準輸出重定向到/ dev/null的,並恢復它回來。我期望屏幕上顯示的唯一輸出是「重定向到/ dev/null」。但是我看到的是「恢復標準輸出回到標準輸出」。

看起來,redirect_stdout()在其先前的語句之前正在運行。

只是爲了完整性,這裏有兩種方法的定義:

void redirect_stdout() 
{ 
    dump_fd = open("/dev/null", O_RDWR, 0777); 
    dup2(dump_fd, STDOUT_FILENO); 
    cout << endl; 
} 

void restore_stdout() 
{ 
    dup2(saved_fd, STDOUT_FILENO); 
    cout << endl; 
} 

爲什麼我看不到第一COUT輸出?

+4

我的水晶球說,這是因爲你在重定向之前不要刷新。嘗試使用'<< std :: flush'。 – HolyBlackCat

+0

標準的'基於iostreams'的類在內部使用很多緩衝。我不知道沖洗它們是否足夠,或者如果這將永遠是不確定的,但它是我開始的地方。 –

回答

1

在這兩種情況下,答案都是「緩衝」。發送輸出到cout時,直到緩衝區已滿或直到刷新輸出爲止,纔會將其發送到文件描述符1。

的解決方法是刷新輸出:

saved_fd = dup(STDOUT_FILENO); 
std::cout << "Redirecting std out to /dev/null" << std::flush; 
redirect_stdout() 
<do some stuff> 
std::cout << "Restoring std out back to standard output" << std::flush; 
restore_stdout(); 

(而不是std::flush,你也可以使用std::endl它輸出一個換行符並刷新輸出)。