C++ C和C中几乎相同的代码在执行时间上有很大差异(x9)++;

C++ C和C中几乎相同的代码在执行时间上有很大差异(x9)++;,c++,c,performance,gcc,iostream,C++,C,Performance,Gcc,Iostream,我试图从www.spoj.com上解决这个问题: 你真的不必读它,如果你好奇的话就去读:) 首先,我在C++中实现了它(这是我的解决方案): #包括 使用名称空间std; int main(){ 输入的无符号int num; 无符号整数事实数; 尾随零的无符号int num; std::ios_base::sync_with_stdio(false);//关闭与C库的stdio缓冲区的同步(从https://stackoverflow.com/a/22225421/5218277) cin>>输

我试图从www.spoj.com上解决这个问题:

你真的不必读它,如果你好奇的话就去读:)

首先,我在C++中实现了它(这是我的解决方案):

#包括
使用名称空间std;
int main(){
输入的无符号int num;
无符号整数事实数;
尾随零的无符号int num;
std::ios_base::sync_with_stdio(false);//关闭与C库的stdio缓冲区的同步(从https://stackoverflow.com/a/22225421/5218277)
cin>>输入的数量;
while(输入的数量--)
{
cin>>事实数字;
尾随零的数量=0;

对于(unsigned int fives=5;fives这两个程序做完全相同的事情。它们使用相同的精确算法,并且由于其低复杂性,它们的性能主要取决于输入和输出处理的效率

使用
scanf(“%d”和&fact\u num)扫描输入实际上,在编译时已知转换类型,而C++ C++编译器直接调用正确的解析器。对于输出,同样如此。甚至连写一个单独的调用的点也不贵。对于
printf(“%s”,“\n”);
,但C编译器可以将其编译为对
putchar('\n');
的调用

<> P.>查看I/O和计算的复杂性,C++版本应该比C版本快。

完全禁用“代码> STDUD/<代码>的缓冲,将C实现慢一些,甚至比C++版本慢。AlexLop的另一个测试,使用了<代码> FFLUHU(STDUT)在最后的代码> Prtff<代码>产生与C++版本类似的性能。它不像完全禁用缓冲一样慢,因为输出是以小的块写入系统而不是一次一个字节。

这似乎指向C++库中的一个特定行为:我怀疑您的系统实现了<代码> CIN < /C>和 CUT//COD>当从<代码> CIN < /代码>请求输入时,将输出刷新到Cuth>代码>。一些C库也这样做,但通常只在读/写终端时才有。由www.spoj.com网站完成,可能会将输入和输出重定向到文件或从文件中重定向

LoxLopp做了另一个测试:在向量中同时读取所有输入,然后计算和写入所有输出,这有助于理解C++版本为什么慢得多。它提高了C版本的性能,这证明了我的观点,并且消除了C++格式代码的疑虑。

Blastfurnace的另一个测试,将所有输出存储在<代码> STD::OSTRIGSTROUND和在最后一次爆炸中的刷新,确实提高了C++基本版本C的性能。 将来自

cin
的输入和输出隔行扫描到
cout
似乎会导致非常低效的I/O处理,从而破坏流缓冲方案。将性能降低了10倍

PS:您的算法对于
事实数>=UINT\u MAX/5
是不正确的,因为
五个*=5
将在成为
>事实数
之前溢出并环绕。您可以通过将
五个
设置为
无符号长
无符号长
来纠正此问题,如果其中一种类型大于
无符号长
ned int
。也使用
%u
作为
scanf
格式。你很幸运,www.spoj.com上的人在基准测试方面没有太严格

<>编辑:正如vitaux后来解释的那样,这个行为确实是由C++标准强制执行的。<代码> CIN <代码>默认与 CUT绑定。输入代码的输入操作从代码> CIN < /代码>中输入缓冲区需要重新填充,这将导致<代码> CUT<代码>刷新未决的输出。在OP的实现中, CIN < /C> >似乎是流感。sh
cout
系统化,这有点过分,明显效率低下

伊利亚·波波夫为此提供了一个简单的解决方案:
cin
可以从
cout
解开,除了
std::ios\u base::sync_with_stdio(false);

cin.tie(nullptr);


也注意到,当使用<代码> STD::EntL\/Cord>而不是<代码> \n′/Cube >时,也会发生这种强制刷新。在代码< >代码> >代码>上生成一个结束行。将输出行更改为更多的C++习惯用法和无害查找<代码> cOUT> P>问题是,引用:

从std::cin的任何输入、到std::cerr的输出或程序终止都会强制调用std::cout.flush()

这很容易测试:如果更换

cin >> fact_num;

< > >代码> CIN > NUMION输入< <代码> >但保持<代码> cOUT/COD> >在C++版本(或,相当于IoSt流版本)中,与C 1:

相比,将获得几乎相同的性能。

如果保留
cin
但替换,也会发生同样的情况

cout << num_of_trailing_zeros << "\n";
一个简单的解决方案是解开Ilya Popov提到的
cout
cin

cin.tie(nullptr);
在某些情况下,允许标准库实现省略对flush的调用,但并非总是如此。以下引用自C++14 27.7.2.1.3(感谢chqrlie):

类basic_istream::sentry:首先,如果is.tie()不是空指针,则函数调用is.tie()->flush(),以将输出序列与任何关联的外部C流同步。但如果的put区域为.tie(),则可以抑制此调用是空的。此外,允许实现将对flush的调用推迟到调用is.rdbuf()->underflow()为止。如果在销毁sentry对象之前未发生此类调用,则可以完全消除对flush的调用


当您同时使用
cin
coutiostream
s更快的技巧
scanf("%d", &fact_num);
cout << num_of_trailing_zeros << "\n";
printf("%d", num_of_trailing_zeros);
printf("%s","\n");
cin.tie(nullptr);
cin.tie(nullptr);
std::string name;
cout << "Enter your name:";
cin >> name;
std::string line;
for (int i = 0; i < n && std::getline(std::cin, line); ++i)
{
    int x = std::stoi(line);
}