IT-Swarm.Net

在C++程序中使用scanf()比使用cin更快?

我不知道这是否属实,但当我在其中一个问题提供网站上阅读FAQ时,我发现了一些引起我注意的东西:

检查输入/输出方法。在C++中,使用cin和cout太慢了。使用这些,您将保证无法通过适当的输入或输出解决任何问题。请改用printf和scanf。.

有人可以澄清一下吗?在C++程序中真的使用 scanf() 比使用 cin >>某事 ?更快如果是,那么在C++程序中使用它是一个好习惯吗?我认为这是C特定的,虽然我只是学习C++ ...

105
zeroDivisible

这是一个简单案例的快速测试:一个程序,用于读取标准输入的数字列表和XOR所有数字。.

iostream版本:

#include <iostream>

int main(int argc, char **argv) {

  int parity = 0;
  int x;

  while (std::cin >> x)
    parity ^= x;
  std::cout << parity << std::endl;

  return 0;
}

scanf版本:

#include <stdio.h>

int main(int argc, char **argv) {

  int parity = 0;
  int x;

  while (1 == scanf("%d", &x))
    parity ^= x;
  printf("%d\n", parity);

  return 0;
}

结果

使用第三个程序,我生成了一个包含33,280,276个随机数的文本文件。执行时间是:

iostream version:  24.3 seconds
scanf version:      6.4 seconds

更改编译器的优化设置似乎根本没有改变结果。.

因此:确实存在速度差异。.


编辑:用户clyfish 指出下面 速度差异很大程度上是由于iostream I/O功能保持与C I/O功能的同步。我们可以通过调用std::ios::sync_with_stdio(false);来关闭它:

#include <iostream>

int main(int argc, char **argv) {

  int parity = 0;
  int x;

  std::ios::sync_with_stdio(false);

  while (std::cin >> x)
    parity ^= x;
  std::cout << parity << std::endl;

  return 0;
}

新结果:

iostream version:                       21.9 seconds
scanf version:                           6.8 seconds
iostream with sync_with_stdio(false):    5.5 seconds

C++ iostream赢了! 事实证明,这种内部同步/刷新通常会减慢iostream i/o的速度。如果我们不混合stdio和iostream,我们可以关闭它,然后iostream是最快的。.

代码: https://Gist.github.com/3845568

193
nibot

快速,可靠且价格合理的云托管

注册并在30天内获得$50奖金!

http://www.quora.com/Is-cin-cout-slower-than-scanf-printf/answer/Aditya-Vishwakarma

cin/cout的性能可能很慢,因为它们需要与底层C库保持同步。如果要使用C IO和C++ IO,这是必不可少的。.

但是,如果您只打算使用C++ IO,那么只需在任何IO操作之前使用以下行。.

std::ios::sync_with_stdio(false);

有关这方面的更多信息,请查看相应的 libstdc ++文档 。.

60
clyfish

可能scanf比使用流更快一些。虽然流提供了很多类型安全性,并且不必在运行时解析格式字符串,但它通常具有不需要过多内存分配的优点(这取决于您的编译器和运行时)。也就是说,除非性能是你唯一的最终目标并且你处于关键路径,否则你应该更喜欢更安全(更慢)的方法。.

Herb Sutter在这里写了一篇非常好吃的文章“ 庄园农场的字符串格式化程序 ”,他详细介绍了sscanflexical_cast等字符串格式化程序的性能,以及它们使得它们运行缓慢或者很快。这有点类似,可能会影响C风格IO和C++风格之间的性能。与格式化程序的主要区别往往是类型安全性和内存分配数。.

42
1800 INFORMATION

我刚刚花了一个晚上在UVa Online上解决问题(Factovisors,一个非常有趣的问题,请查看):

http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=35&page=show_problem&problem=1080

我在提交时获得了TLE(超出时间限制)。在这些解决问题的在线评判网站上,您有大约2-3秒的时间限制来处理可能用于评估您的解决方案的数千个测试用例。对于像这样的计算密集型问题,每微秒都很重要。.

我正在使用建议的算法(在论坛的讨论论坛中阅读),但仍然得到TLE。.

我将“cin >> n >> m”更改为“scanf(”%d%d“,&n,&m)”和几个微小的“couts”改为“printfs”,我的TLE变成了“Accepted”!

所以,是的,它可以产生很大的不同,特别是在时间限制很短的情况下。.

16
Bogatyr

如果您关心性能和字符串格式,请查看 Matthew Wilson的FastFormat 库。.

编辑 - 链接到该库的出版物: http://accu.org/index.php/journals/1539

6
xtofl

是的iostream比cstdio慢。.
是的,如果你是用C++开发的话,你可能不应该使用cstdio。.
话虽如此,如果你不关心格式化,输入安全性,等等,等等,有更快的方式来获取I/O而不是scanf ......

例如,这是从STDIN获取数字的自定义例程:

inline int get_number()
{
    int c;        
    int n = 0;

    while ((c = getchar_unlocked()) >= '0' && c <= '9')
    {
        // n = 10 * n + (c - '0');
        n = (n << 3) + ( n << 1 ) + c - '0';
    }
    return n;
}
2
pedro.lupin

有stdio实现( libio ),它将FILE *实现为C++ streambuf,将fprintf实现为运行时格式解析器。 IOstream不需要运行时格式解析,这些都是在编译时完成的。因此,在共享后端的情况下,期望iostream在运行时更快是合理的。.

2
MSalters

问题是cin涉及很多开销,因为它为scanf()调用提供了一个抽象层。如果你正在编写C++软件,那么你不应该使用scanf()而不是cin,因为希望cin用于。如果你想要性能,你可能不会在C++中编写I/O.

1
dreamlax

一般使用的语句cincout似乎比C++中的scanfprintf慢,但实际上它们更快!

问题是:在C++中,无论何时使用cincout,默认情况下都会发生同步过程,以确保如果在程序中同时使用scanfcin,则它们彼此同步工作。此同步过程需要时间。因此cincout APPEAR会变慢。.

但是,如果同步过程设置为不发生,则cinscanf快。.

要跳过同步过程,请在main()开头的程序中包含以下代码段:

std::ios::sync_with_stdio(false);

访问 本网站 了解更多信息。.

0
Prasoon Varshney
#include <stdio.h>
#include <unistd.h>

#define likely(x)       __builtin_expect(!!(x), 1)
#define unlikely(x)     __builtin_expect(!!(x), 0)

static int scanuint(unsigned int* x)
{
  char c;
  *x = 0;

  do
  {
      c = getchar_unlocked();
      if (unlikely(c==EOF)) return 1;
  } while(c<'0' || c>'9');

  do
  {
      //*x = (*x<<3)+(*x<<1) + c - '0';
      *x = 10 * (*x) + c - '0';
      c = getchar_unlocked();
      if (unlikely(c==EOF)) return 1;
  } while ((c>='0' && c<='9'));

  return 0;
}

int main(int argc, char **argv) {

  int parity = 0;
  unsigned int x;

  while (1 != (scanuint(&x))) {
    parity ^= x;
  }
  parity ^=x;
  printf("%d\n", parity);

  return 0;
}

文件末尾有一个错误,但是这个C代码比速度更快的C++版本要快得多。.

paradox@scorpion 3845568-78602a3f95902f3f3ac63b6beecaa9719e28a6d6 ▶ make test        
time ./xor-c < Rand.txt
360589110

real    0m11,336s
user    0m11,157s
sys 0m0,179s
time ./xor2-c < Rand.txt
360589110

real    0m2,104s
user    0m1,959s
sys 0m0,144s
time ./xor-cpp < Rand.txt
360589110

real    0m29,948s
user    0m29,809s
sys 0m0,140s
time ./xor-cpp-noflush < Rand.txt
360589110

real    0m7,604s
user    0m7,480s
sys 0m0,123s

原始C++耗时30秒C代码需要2秒。.

0
hexec