在C++中,cout和printf哪个执行速度更快?

38

我长时间使用C++编程。 我一直在想哪个执行速度更快,printf还是cout

情况:我正在使用C++设计应用程序,有一些限制,例如执行时间限制。 我的应用程序在控制台上有许多打印命令。 那么哪个更适合,printf还是cout


7
如果这对你很重要,写一个能够同时完成两个任务的小应用程序并计时。这个过程只需要花费你15分钟左右的时间。 - anon
4
@Neil: 这并不是那么简单。std::cout和operator<<会导致在调用点产生更多的代码。所有printf逻辑都位于CRT中,但使用运行时逻辑来解释参数字符串。因此,具有许多调用点和许多不同格式指令的大型程序可能会看到与仅具有大型“for(a lot) { printf("%d",i); }”的小型测试程序不同的影响。 - MSalters
@MSalters - 不适用于执行控制台 I/O 的程序 - 程序将受到 I/O 限制。而你所说的是永远不测试任何东西的论点。 - anon
我认为可以公正地说,如果有什么区别的话,那就是printf更快。(是的,我进行了测量,是的,我关闭了stdio同步 - 所有这些都比cout慢)。 - Johannes Schaub - litb
可能是哪个更快,哪个更灵活:printf还是cout?的重复问题。 - phuclv
15个回答

34

两种方式都有它们自己的开销。根据您要打印的内容,任何一种方式都可能更快。

以下是我想到的两个要点 -

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

在实践中,除了最奇怪的情况外,差异都不应该有影响。如果您认为真的很重要-那就测量一下!

编辑 -
哦,见鬼,我不相信我正在做这件事,但出于记录的目的,在我的非常特定的测试用例中,使用MSVC在发布状态下编译 -

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

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

(平均10次运行)。

差异如此微小,这可能意味着什么都没有...


3
既不复杂的继承层次结构,也不是单纯的对象传递会引入额外的开销。 - Dave Van den Eynde
3
复杂的继承层次通常意味着较少的局部性,这会影响性能。而传递对象——嗯——会传递本来不需要传递的对象……但我完全同意这些只是轶事。 - Hexagon
我们已经得到了结果。您的快速基准测试表明,差异确实是微不足道的 - cout可能具有的小优势可能可以通过其他方式获得,或者是特定情况下的某些因素。 - Noldorin
2
Noldorin - 完全正确。这里没有任何意外。如果我稍微调整一下要打印的内容(比如添加前导零或其他格式,或在数字之间添加一些额外的字符串),可能会显示相反的结果……但是,够了。生命中有更好的事情要做。 - Hexagon
@Hexagon,继承和局部性有什么关联? - Dave Van den Eynde
Dave - 继承通常(但并不总是)意味着调用多个可能不在内存中局部放置的小函数。这可能会增加额外的成本——既因为调用更多函数,也因为需要更多的缓存行。 - Hexagon

23
你真的需要关心哪个执行速度更快吗?它们都仅用于将文本打印到控制台/stdout,这通常不是需要超高效率的任务。就此而言,我想速度上可能没有太大差异(尽管一个人可能会期望printf稍微快一点,因为它缺少面向对象的小复杂性)。然而,考虑到我们在处理I/O操作,即使有轻微的差异,也可能被I/O开销淹没。当然,如果您比较写入文件的等效方法,那肯定是这种情况。 printf只是在C中将文本输出到stdout的标准方法。 'cout'管道只是在C ++中将文本输出到stdout的标准方法。
说了这么多,comp.lang.cc组上有一个讨论相同问题的线程。然而,共识似乎是您应该选择其中之一,原因并非出于性能考虑。

14
我不会说这并不重要。我当然可以想象到一些情况下它是很重要的(例如当你需要编写数百万行的日志记录时)。但这些情况应该是非常罕见的。 - Hexagon
9
将128k向量数据转换为文本时,细微的差别确实非常重要。 - peterchen
2
@peterchen:压倒性的证据表明情况并非如此。 :) - Noldorin
28
当人们问一个简单的问题,比如“X比Y更快吗?”而不是得到该问题的答案,"回答者"总是告诉他们这并不重要,或者那只是微小优化之类的话语,我认为这真的很烦人。 - Tara
3
在嵌入式系统中,这确实很重要! - jaques-sam
显示剩余4条评论

15

6
至少在Windows平台上,向控制台写入数据是一个巨大的瓶颈,因此“嘈杂”的控制台模式程序将比静音模式程序慢得多。因此,在该平台上,用于处理控制台输出的库函数的微小差异可能在实践中没有任何显着差别。
在其他平台上可能会有所不同。此外,这也取决于您要做的有用工作相对于控制台输出的数量。
最后,这取决于您的平台实现C和C ++ I/O库的方式。
因此,对于这个问题没有普遍的答案。

完全同意。我有一个测试程序在stdout上输出了大量的日志信息。在Windows的常规控制台窗口中,它运行了15分钟。如果我隐藏窗口,它只需要5分钟就能运行。如果你在Linux上使用KDE,同样的情况也适用于Konsole。我建议减少stdout/stderr打印的数据量,并使用日志文件代替详细信息,将控制台保持最小化。幸运的是,这个控制台程序非常高效:http://sourceforge.net/projects/console - Philippe F

5
性能不是比较的问题;在开发控制台程序等方面,实际上并没有什么需要考虑性能的地方。然而,有几个点需要考虑:
- Iostream使用运算符链而不是va_args。这意味着,您的程序不能因为传递了错误数量的参数而崩溃。这可能会在printf中发生。 - Iostream使用运算符重载而不是va_args——这意味着您的程序不能因为传递了int类型而期望string类型而崩溃。这可能会在printf中发生。 - Iostream没有本地支持格式字符串(这是#1和#2的主要根本原因)。这通常是一件好事,但有时它们很有用。Boost格式库将此功能引入iostreams,为那些需要它的人提供定义行为(抛出异常)而不是未定义行为(如printf的情况)。目前,这超出了标准范围。 - 与其printf相对应的iostreams可以直接处理可变长度缓冲区,而不是被迫处理硬编码的废物。
选择cout即可。

4
我最近在Windows上开发了一个使用CopyFileEx复制文件的C++控制台应用程序,并且在每次复制时将“to”和“from”路径回显到控制台,然后在操作结束时显示平均吞吐量。
当我使用printf来回显字符串时,吞吐量为4mb / sec;而当我使用std :: cout替换printf时,吞吐量下降到800kb / sec。
我想知道为什么std :: cout调用会更加昂贵,甚至为了更好地比较这些调用,我在每次复制时都回显相同的字符串。我进行了多次运行以平衡比较,但是4倍差异仍然存在。
然后我在stackoverflow上找到了这个答案。
打开stdout缓冲区解决了问题,现在我的printf和std :: cout的吞吐量几乎相同。
我没有深入研究printf和cout在控制台输出缓冲方面的区别,但在开始写入控制台之前设置输出缓冲区解决了我的问题。

3

3
如果你正在使用C ++,你应该使用cout而不是printf,因为printf属于C函数族。有许多对cout进行的改进,你可能会从中受益。至于速度,由于控制台I / O本来就很慢,所以这不是问题。

2

实际上,我一直发现printf比cout更快。但是,cout在类型安全方面为您提供了更多的帮助。同时请记住,printf是一个简单的函数,而cout是基于复杂流层次结构的对象,所以比较执行时间并不公平。


我想我同意你的观点,cout比printf做得更多。我问这个问题只是出于好奇,并不是为了比较它们。非常感谢 :) - pirate

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在时间上产生相同的结果。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接