成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

C++性能真的不如C嗎?

開發 后端
眾所周知,C++兼容了C的所有功能,顯然從所有角度去對比分析是不現實的,所以本文從我們常用的輸入輸出即標準流(iostream和stdio)的角度來分析講解。

最近在知乎上看了篇帖子,題目是為什么C++沒有C語言快,如下圖:

恰好之前研究過這塊,所以借助本文,分析下這個問題(無意于語言之爭,單純是從技術角度??)。

眾所周知,C++兼容了C的所有功能,顯然從所有角度去對比分析是不現實的,所以本文從我們常用的輸入輸出即標準流(iostream和stdio)的角度來分析講解。

示例

為了更加直觀地來對比分析,寫了個示例,通過scanf和cin讀文件,然后分析兩種方式的性能高低,代碼如下:

#include <chrono>
#include <functional>
#include <iostream>
#include <fstream>
const int num=1000000;
void time_report(const std::function<void()> &f1, const std::function<void()> &f2) {
auto start = std::chrono::high_resolution_clock::now();
f1();
auto end = std::chrono::high_resolution_clock::now();
std::cout << "cin cost " << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count() << "ms" << std::endl;
start = std::chrono::high_resolution_clock::now();
f2();
end = std::chrono::high_resolution_clock::now();
std::cout << "scanf cost " << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count() << "ms" << std::endl;
}
void write() {
std::ofstream file("./data");
for(int i = 0; i < num; ++i) {
file << rand() <<' ';
if((i + 1) % 20 == 0) {
file << std::endl;
}
}
}
int main() {
write();

time_report([](){
freopen("./data","r",stdin);
int n = 0;
for(int i=0; i<num; i++) {
std::cin >> n;
}
}, [](){
freopen("./data","r",stdin);
int n = 0;
for(int i = 0; i < num; ++i) {
scanf("%d", &n);
}
});
return 0;
}

編譯,運行之后,輸出如下:

cin cost 686ms
scanf cost 189ms

從上述輸出來看,cin的耗時是scanf的3倍多,果真如此么?

sync_with_stdio

C++性能真的差C這么多嗎?直接顛覆了對C++的認知,即使性能真的低,也得知道為什么低吧,于是開始研究,發現C++為了兼容C,在C標準流(stdio)和C++標準流(iostrem)保持同步,這樣就可以混合使用C和C++風格的I/O,且能保證得到合理和預期的結果,而正是這個同步導致C++在cin性能上有損失。如果禁用同步,則允許C++流擁有自己的獨立緩沖區,這樣性能就會提升很多。

那么是否可以禁用該同步功能呢?

C++提供了一個函數std::ios::sync_with_stdio,聲明如下:

static bool sync_with_stdio(bool __sync = true);

如果參數為false,則代表禁用此同步。從上面聲明可以看出,默認情況下 __sync = true也就是說禁用同步,而如果__sync為false的話,則會有如下操作:

bool
ios_base::sync_with_stdio(bool __sync) {
bool __ret = ios_base::Init::_S_synced_with_stdio;

if (!__sync && __ret) {
// ...
cout.rdbuf(&buf_cout);
cin.rdbuf(&buf_cin);
cerr.rdbuf(&buf_cerr);
clog.rdbuf(&buf_cerr);
// ...
}
return __ret;
}

從上述代碼,進一步驗證了我們上面的說法,如果禁用了同步功能,則C++流使用自己的緩沖區buf_cin(此處以cin為例),幾種buffer的定義如下:

typedef char fake_filebuf[sizeof(stdio_filebuf<char>)]
__attribute__ ((aligned(__alignof__(stdio_filebuf<char>))));
fake_filebuf buf_cout;
fake_filebuf buf_cin;
fake_filebuf buf_cerr;

好了,截止到現在,我們已經搞清楚了為什么C++流性能要慢于C,為了驗證是否真的是因為使用了同步功能而導致的性能差異,使用std::ios::sync_with_stdio(false)關閉同步,代碼示例如下:

#include <chrono>
#include <functional>
#include <iostream>
#include <fstream>
const int num=1000000;
void time_report(const std::function<void()> &f1, const std::function<void()> &f2) {
auto start = std::chrono::high_resolution_clock::now();
f1();
auto end = std::chrono::high_resolution_clock::now();
std::cout << "cin cost " << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count() << "ms" << std::endl;
start = std::chrono::high_resolution_clock::now();
f2();
end = std::chrono::high_resolution_clock::now();
std::cout << "scanf cost " << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count() << "ms" << std::endl;
}
void write() {
std::ofstream file("./data");
for(int i = 0; i < num; ++i) {
file << rand() <<' ';
if((i + 1) % 20 == 0) {
file << std::endl;
}
}
}
int main() {
std::ios::sync_with_stdio(false);
write();
time_report([](){
freopen("./data","r",stdin);
int n = 0;
for(int i=0; i<num; i++) {
std::cin >> n;
}
}, [](){
freopen("./data","r",stdin);
int n = 0;
for(int i = 0; i < num; ++i) {
scanf("%d", &n);
}
});
return 0;
}

編譯,運行后,輸出如下:

cin cost 178ms
scanf cost 189ms

可以看出禁用同步后,二者的性能基本一致。

既然禁用同步后,C++流的性能與C基本一致,那么是否直接禁用呢?答案是依賴于具體的使用場景。

1、同步的C++流是線程安全的,也就說來自不同線程的輸出可能會交錯,但數據不會產生競爭,而如果禁用同步,則可能出現意想不到的結果。

2、如果禁用了同步功能,輸入輸出順序可能會得不到我們想要的結果。

#include <stdio.h>
#include <iostream>
int main() {
std::cout << "a ";
printf("b ");
std::cout << "c ";
return 0;
}

上述代碼執行后,輸出a b c ,符合我們的預期。

如果加上禁用同步代碼,如下:

#include <stdio.h>
#include <iostream>
int main() {
std::ios_base::sync_with_stdio(false);
std::cout << "a ";
printf("b ");
std::cout << "c ";
return 0;
}

編譯、運行之后,結果為a c b,與我們期望的不一致。

結語

如果使用C編程,那么使用C stdio,而如果使用C++編程,則建議使用C++ I/O。如果在某些特殊場景下,需要混合使用,那么強烈建議不要禁用同步,否則會得到意想不到的結果。

責任編輯:龐桂玉 來源: C語言與C++編程
相關推薦

2015-09-07 13:55:53

PHPC++

2010-01-21 10:23:53

C++代碼

2010-01-15 16:45:35

C++語言

2010-01-26 09:24:53

C++語言

2010-01-14 10:34:02

C++語言

2010-01-20 10:14:53

C++程序

2010-01-20 17:23:03

C++編程語言

2010-01-14 13:24:49

CC++語言

2010-01-14 14:55:14

C++編譯器

2010-01-21 17:14:40

C++兼容

2010-01-14 10:06:30

C++模板

2010-01-18 11:12:36

2021-06-10 09:40:12

C++性能優化Linux

2024-12-27 09:29:09

2014-04-17 10:37:43

C++.NET Native

2021-07-11 18:04:04

C語言

2010-01-14 17:52:02

2024-06-24 12:41:40

2011-07-14 17:45:06

CC++

2010-01-21 14:07:14

CC++聲明
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 中文字幕蜜臀av | 紧缚调教一区二区三区视频 | 久久99精品久久久久久噜噜 | 亚洲视屏| 色婷婷激情 | 亚洲国产一区二区在线 | 国产精品日韩欧美一区二区三区 | 亚洲精品电影在线 | 久久综合久 | 户外露出一区二区三区 | 欧美日韩电影一区 | 国产精品免费大片 | 国产色婷婷精品综合在线手机播放 | 三级视频网站 | 午夜小电影 | 在线一区| 涩涩99| 亚洲一二三视频 | 欧美日韩国产一区二区 | 在线免费观看毛片 | 久在线视频播放免费视频 | 日韩h | 狠狠操av | 久久国产成人 | 国产丝袜一区二区三区免费视频 | 久久偷人 | 精品国产99 | 欧美狠狠操 | 午夜精品久久久久久久久久久久久 | 电影在线 | 亚洲一区二区三区在线免费 | 亚洲中午字幕 | 国产精品久久久免费 | 日韩中文不卡 | 天天综合操 | 国产精彩视频在线观看 | 一区二区精品 | 黄色在线免费观看 | 国产精品久久久久久久久久久久久久 | 日韩在线视频一区二区三区 | 日韩一区二区三区视频在线观看 |