upd in 20210927 : 部分測試在NOI Linux 2.0虛擬機下測試。測試環境如下:
CPU : i3 1115G4 @ 1C2T
RAM :2G
編譯選項 g++ test.cpp -o test -std=c++14
0.前置環境:
計算機配置:
CPU : i5 7500
RAM : 8G
系統:Win7 64位
測試硬盤:intel 256G SSD
無吸氧優化,使用C++98, GCC 4.9.2 64 Bit
1. cout、printf輸出字符串,無換行
代碼:
//test 1 : cout VS printf in output string
#include <iostream>
#include <cstdio>
#include <ctime>
using namespace std;
int T = 10000000;//1e7
clock_t st, co, pri;
signed main(){
freopen("waste.out","w",stdout);
st = clock();
for(int i = 1; i <= T; ++i){
cout << "LKYAKIOI";
}
co = clock();
for(int i = 1; i <= T; ++i){
printf("LKYAKIOI");
}
pri = clock();
freopen("result.out","w",stdout);
cout << "cout : " << 1.0*(co-st) / (CLOCKS_PER_SEC) << "s" << endl;
cout << "printf : " << 1.0*(pri-co) / (CLOCKS_PER_SEC) << "s" << endl;
return 0;
}
結果:
cout : 0.617s
printf : 21.279s
2. cout、printf輸出int內整數,無換行
代碼:
//test 2 : cout VS printf in output int
#include <iostream>
#include <cstdio>
#include <ctime>
using namespace std;
const int T = 10000000;//1e7
clock_t st, co, pri, pus, puc;
signed main(){
freopen("waste.out","w",stdout);
st = clock();
for(int i = 1; i <= T; ++i){
cout << i;
}
co = clock();
for(int i = 1; i <= T; ++i){
printf("%d", i);
}
pri = clock();
freopen("result.out","w",stdout);
cout << "cout : " << 1.0*(co-st) / (CLOCKS_PER_SEC) << "s" << endl;
cout << "printf : " << 1.0*(pri-co) / (CLOCKS_PER_SEC) << "s" << endl;
return 0;
}
結果:
cout : 0.723s
printf : 21.012s
upd : 於NOI Linux環境下的結果:
cout : 0.415719s
printf : 0.458123s
cout : 0.391156s
printf : 0.467886s
cout : 0.421311s
printf : 0.547006s
3. cout、printf輸出long long內整數,無換行
代碼:
//test 3 : cout VS printf in output long long
#include <iostream>
#include <cstdio>
#include <ctime>
using namespace std;
const int T = 10000000;//1e7
clock_t st, co, pri, pus, puc;
signed main(){
freopen("waste.out","w",stdout);
st = clock();
for(int i = 1; i <= T; ++i){
cout << 1ll * i * T;
}
co = clock();
for(int i = 1; i <= T; ++i){
printf("%lld", 1ll*i*T);
}
pri = clock();
freopen("result.out","w",stdout);
cout << "cout : " << 1.0*(co-st) / (CLOCKS_PER_SEC) << "s" << endl;
cout << "printf : " << 1.0*(pri-co) / (CLOCKS_PER_SEC) << "s" << endl;
return 0;
}
結果:
cout : 1.024s
printf : 23.381s
4. cout、printf輸出double,保留6位小數,無換行
為了模擬常見環境,我們保留6位小數,所以用了setprecision()
函數
代碼:
//test 4 : cout VS printf in output double
#include <iostream>
#include <cstdio>
#include <ctime>
#include <iomanip>
using namespace std;
const int T = 10000000;//1e7
clock_t st, co, pri, pus, puc;
signed main(){
freopen("waste.out","w",stdout);
st = clock();
for(double i = 1; i <= T; ++i){
cout << fixed << setprecision(6) << 11.45141919 * i;
}
co = clock();
for(double i = 1; i <= T; ++i){
printf("%.6lf", 11.45141919 * i);
}
pri = clock();
freopen("result.out","w",stdout);
cout << "cout : " << 1.0*(co-st) / (CLOCKS_PER_SEC) << "s" << endl;
cout << "printf : " << 1.0*(pri-co) / (CLOCKS_PER_SEC) << "s" << endl;
return 0;
}
結果:
cout : 30.008000s
printf : 29.687000s
5. cout、printf輸出換行(對cout同時測試endl和\n)
代碼:
//test 5 : cout VS printf in endline
#include <iostream>
#include <cstdio>
#include <ctime>
#include <iomanip>
using namespace std;
const int T = 10000000;//1e7
clock_t st, co, el, pri, pus, puc;
signed main(){
freopen("waste.out","w",stdout);
st = clock();
for(int i = 1; i <= T; ++i){
cout << '\n';
}
co = clock();
for(int i = 1; i <= T; ++i){
cout << endl;
}
el = clock();
for(int i = 1; i <= T; ++i){
printf("\n");
}
pri = clock();
freopen("result.out","w",stdout);
cout << "cout : " << 1.0*(co-st) / (CLOCKS_PER_SEC) << "s" << endl;
cout << "endl : " << 1.0*(el-co) / (CLOCKS_PER_SEC) << "s" << endl;
cout << "printf : " << 1.0*(pri-el) / (CLOCKS_PER_SEC) << "s" << endl;
return 0;
}
結果:
cout : 0.401s
endl : 11.698s
printf : 18.655s
Bonus: cout、printf、puts、putchar輸出字符串,無換行
代碼:
//bonus : cout VS printf VS puts VS putchar at output string
#include <iostream>
#include <cstdio>
#include <ctime>
using namespace std;
int T = 10000000;//1e7
clock_t st, co, pri, pus, puc;
signed main(){
freopen("waste.out","w",stdout);
st = clock();
for(int i = 1; i <= T; ++i){
cout << "LKYAKIOI" << '\n';
}
co = clock();
for(int i = 1; i <= T; ++i){
printf("LKYAKIOI\n");
}
pri = clock();
for(int i = 1; i <= T; ++i){
puts("LKYAKIOI");
}
pus = clock();
for(int i = 1; i <= T; ++i){
putchar('L');putchar('K');putchar('Y');
}
puc = clock();
freopen("result.out","w",stdout);
cout << "cout : " << 1.0*(co-st) / (CLOCKS_PER_SEC) << "s" << endl;
cout << "printf : " << 1.0*(pri-co) / (CLOCKS_PER_SEC) << "s" << endl;
cout << "puts : " << 1.0*(pus-pri) / (CLOCKS_PER_SEC) << "s" << endl;
cout << "putchar: " << 1.0*(puc-pus) / (CLOCKS_PER_SEC) << "s" << endl;
return 0;
}
結果:
cout : 1.034s
printf : 22.068s
puts : 0.978s
putchar: 0.968s
結論
除了在輸出double的時候速度比printf
略慢(並且很有可能是因為使用了setprecision()
函數),在其他的時候基本上就是碾壓。並且本文中並沒有給cout
關閉流同步——這在實際使用中很常見(畢竟不太可能會在同一篇代碼中使用兩個年代的東西,而且本身同時用scanf/printf
與cin/cout
本身就充滿玄學容易出錯)。
所以,基本可以認為,在不輸出浮點數的使用環境中,cout
是更好的選擇。
此外,在輸出換行的實驗中,我們發現使用cout
輸出'\n'
比輸出endl
換行來快得多。這在實際使用中也可以作為常數優化。
當然,由bonus可看出,在大量輸出string
(如輸出Yes/No
類的)用cout就圖一樂,真要最快還是得用puts。
upd:
事實上好像差距不大,但是cout
還是比printf
快一些