34

我已经用 C++ 编码很长时间了。我一直想知道哪个执行速度更快printfcout

情况:我正在用 C++ 设计一个应用程序,我有一些限制,例如执行时间限制。我的应用程序在控制台上加载了打印命令。那么哪一个更可取printfcout

4

15 回答 15

32

每个都有自己的开销。根据您打印的内容,任何一个都可能更快。

想到这里有两点——

printf() 必须解析“格式”字符串并对其进行操作,这会增加成本。
cout 具有更复杂的继承层次结构并传递对象。

在实践中,除了最奇怪的情况外,差异对所有情况都不重要。如果您认为这真的很重要 - 测量!

编辑-
哦,见鬼,我不相信我正在这样做,但为了记录,在我非常具体的测试用例中,使用我非常具体的机器及其非常具体的负载,使用 MSVC 在 Release 中编译 -

打印 150,000 个“Hello, World!”(不使用 endl)大约需要 -
printf() 需要 90 毫秒,cout 需要 79 毫秒。

打印 150,000 个随机双打大约需要 -
printf() 3450ms,cout 3420ms。

(平均超过 10 次运行)。

差异如此之小,这可能没有任何意义......

于 2009-05-22T07:00:33.530 回答
23

你真的需要关心哪个执行速度更快吗?它们都仅用于将文本打印到控制台/标准输出,这通常不是需要超高效率的任务。就此而言,无论如何我都不会想象速度会有很大差异(尽管人们可能会期望速度printf会稍微快一些,因为它缺少面向对象的次要复杂性)。然而,鉴于我们在这里处理的是 I/O 操作,即使是很小的差异也可能会被 I/O 开销所淹没。当然,如果您比较写入文件的等效方法,情况就是如此。

printf只是在 C 中将文本输出到标准输出的标准方法。
“cout”管道只是在 C++ 中将文本输出到标准输出的标准方法。

说了这么多,comp.lang.cc群里有个帖子在讨论同样的问题。然而,共识似乎是您应该出于性能以外的原因选择一个而不是另一个。

于 2009-05-22T07:03:16.550 回答
15

C++ cout 速度慢的原因是与 stdio 的默认同步。

尝试执行以下操作以停用此问题。

ios_base::sync_with_stdio(false)

http://www.cplusplus.com/reference/iostream/ios_base/sync_with_stdio/

http://msdn.microsoft.com/es-es/library/7yxhba01.aspx

于 2011-09-28T07:23:05.870 回答
6

至少在 Windows 上,向控制台写入是一个巨大的瓶颈,因此“嘈杂”的控制台模式程序将远慢于无声的程序。因此,在该平台上,用于处理控制台的库函数的细微差别在实践中可能不会产生显着差异。

在其他平台上可能会有所不同。此外,它还取决于您正在执行多少控制台输出,相对于其他有用的工作。

最后,它取决于您的平台对 C 和 C++ I/O 库的实现。

所以这个问题没有一般的答案。

于 2009-05-22T07:08:06.997 回答
5

性能不是比较问题;想不出任何真正重要的东西(开发控制台程序)。但是,您应该考虑以下几点:

  • Iostreams 使用运算符链接而不是 va_args。这意味着您的程序不会因为您传递了错误数量的参数而崩溃。这可能发生在 printf 中。

  • Iostreams 使用运算符重载而不是 va_args ——这意味着您的程序不会崩溃,因为您传递了一个 int 并且它期待一个字符串。这可能发生在 printf 中。

  • Iostreams 没有对格式字符串的原生支持(这是#1 和#2 的主要原因)。这通常是一件好事,但有时它们很有用。Boost 格式库将此功能带到了 Iostreams 中,供那些需要具有已定义行为(抛出异常)而不是未定义行为(如 printf 的情况)的人使用。这目前不在标准范围内。

  • Iostreams 与它们的 printf 等价物不同,它可以自己直接处理可变长度缓冲区,而不是被迫处理硬编码的垃圾。

去cout。

于 2009-05-22T07:08:50.723 回答
4

我最近在 Windows 上开发一个 C++ 控制台应用程序,该应用程序使用 CopyFileEx 复制文件,并将每个副本的“to”和“from”路径回显到控制台,然后在操作结束时显示平均吞吐量。

当我使用 printf 运行控制台应用程序来回显字符串时,我得到了 4mb/sec,当用 std::cout 替换 printf 时,吞吐量下降到 800kb/sec。

我想知道为什么 std::cout 调用要贵得多,甚至会在每个副本上回显相同的字符串,以便更好地比较调用。我进行了多次运行以平衡比较,但 4 倍的差异仍然存在。

然后我在stackoverflow上找到了这个答案..

打开 stdout 的缓冲就可以了,现在我的 printf 和 std::cout 的吞吐量数字几乎相同。

我还没有深入研究 printf 和 cout 在控制台输出缓冲方面的不同之处,但是在我开始写入控制台之前设置输出缓冲区解决了我的问题。

于 2011-06-17T15:49:56.400 回答
3

另一个 Stack Overflow 问题解决了 C 样式格式化 I/O 与 C++ iostream 的相对速度:

但是请注意,所讨论的基准是针对内存缓冲区的格式化。我猜如果您实际上是在对控制台或文件执行 I/O,那么由于 I/O 占用更多的总时间,相对速度差异会小得多。

于 2009-05-22T07:41:52.227 回答
3

如果您使用的是 C++,则应使用coutasprintf属于 C 系列函数。有许多改进cout,您可能会从中受益。至于速度,这不是问题,因为控制台 I/O 无论如何都会很慢。

于 2009-05-22T07:43:48.417 回答
2

实际上,我一直发现 printf 比 cout 快。但话又说回来,cout 在类型安全方面为您做的更多。还要记住 printf 是一个简单的函数,而 cout 是一个基于复杂流层次结构的对象,因此比较执行时间并不公平。

于 2009-05-22T07:08:44.733 回答
1

要解决这个问题:

#include <iostream>
#include <cstdio>
#include <ctime>
using namespace std;

int main( int argc, char * argcv[] ) {
    const char * const s1 = "some text";
    const char * const s2 = "some more text";
    int x = 1, y = 2, z = 3;
    const int BIG = 2000;
    time_t now = time(0);
    for ( int i = 0; i < BIG; i++ ) {
        if ( argc == 1 ) {
            cout  << i << s1 << s2 << x << y << z << "\n";
        }
        else {
            printf( "%d%s%s%d%d%d\n", i, s1, s2, x, y, z );
        }
    }
    cout << (argc == 1 ? "cout " : "printf " ) << time(0) - now << endl;
}

为 cout 和 printf 生成相同的时序。

于 2009-05-22T08:20:09.450 回答
1

你为什么不做一个实验?平均而言,打印字符串 helloperson;\n 使用 printf 平均需要 2 个时钟滴答,而 cout 使用 endl 需要大量时间 - 1248996720685 个时钟滴答。使用带有 "\n" 的 cout 作为换行符只需要 41981 个时钟滴答。我的代码的短网址如下:

cpp.sh/94qoj

链接可能已过期。

要回答您的问题, printf 更快。

#include <iostream>
#include <string>
#include <ctime>
#include <stdio.h>
using namespace std;
int main()
{
  clock_t one;
  clock_t two;
  clock_t averagePrintf;
  clock_t averageCout;
  clock_t averagedumbHybrid;
  for (int j = 0; j < 100; j++) {
    one = clock();
    for (int d = 0; d < 20; d++) {
      printf("helloperson;");
      printf("\n");
    }
    two = clock();
    averagePrintf += two-one;

    one = clock();
    for (int d = 0; d < 20; d++) {
      cout << "helloperson;";
      cout << endl;
    }
    two = clock();
    averageCout += two-one;

    one = clock();
    for (int d = 0; d < 20; d++) {
      cout << "helloperson;";
      cout << "\n";
    }
    two = clock();
    averagedumbHybrid += two-one;
  }
  averagePrintf /= 100;
  averageCout /= 100;
  averagedumbHybrid /= 100;
  cout << "printf took " << averagePrintf << endl;
  cout << "cout took " << averageCout << endl;
  cout << "hybrid took " << averagedumbHybrid << endl;
}

是的,我确实使用了愚蠢这个词。我首先为自己制作,认为结果很疯狂,所以我搜索了它,最后我发布了我的代码。

希望它有帮助,Ndrewffght

于 2017-03-07T20:17:56.640 回答
0

在引擎盖下,它们都将使用相同的代码,因此速度差异无关紧要。

如果你只在 Windows 上运行,非标准的 cprintf() 可能会更快,因为它绕过了很多流的​​东西。

然而,这是一个奇怪的要求。没有人能读得那么快。为什么不将输出写入文件,然后用户可以在闲暇时浏览文件?

于 2009-05-23T09:21:45.843 回答
0

如果您出于性能原因需要找出原因,则说明您的应用程序存在根本性问题 - 考虑使用其他一些日志记录工具或 UI ;)

于 2009-05-22T07:22:21.777 回答
-2

轶事证据:
我曾经设计了一个日志类来使用 ostream 运算符——实现速度非常慢(对于大量数据)。

我没有对此进行过多分析,所以它也可能是由于没有正确使用 ostreams 造成的,或者仅仅是由于记录到磁盘的数据量很大。(由于性能问题,该课程已被废弃,并且在实践中首选 printf / fmtmsg 样式。)

我同意其他回答,在大多数情况下,这并不重要。如果输出确实是一个问题,您应该考虑避免/延迟它的方法,因为实际的显示更新通常比正确实施的字符串构建成本更高。无论如何,在几毫秒内滚动的数千行信息并不是很丰富。

于 2009-05-22T08:46:02.190 回答
-6

永远不需要问这个问题,因为用户只能比他们两个都读得慢。

如果您需要快速执行,请不要使用任何一种。

正如其他人所提到的,如果您需要操作记录,请使用某种日志记录。

于 2009-05-22T07:43:03.953 回答