std::cout 与 printf 的区别

原答于知乎

二者的定义官方说法是这样的:

1
2
3
4
5
6
7
8
std::cout:

The global objects std::cout and std::wcout control output to a stream buffer of implementation-defined type (derived from std::streambuf),
associated with the standard C output stream stdout.

printf:

Loads the data from the given locations, converts them to character string equivalents and writes the results to a variety of sinks.

好的, 放完洋屁翻译一下:

std::cout, std::cin 是全局对象, operator << 和 operator >> 是流运算符, std::cout 重载了 << 运算符, std::cin 重载了 >> 运算符.
printf 是函数.

看到上面的回答提到了二者混用问题, 说 printf 速度比 cout 要快, 这个其实是不对的. 我们看上面std::cout 解释的最后一句, std::cout 是默认与C标准输出stdout 同步的(std::cin 同理), 所以会有额外的运算. C++ 提供了 std::ios_base::sync_with_stdio 这样一个函数来设置是否同步, 但是关闭了同步之后可能会出现错误.

然而, 我们在看 cin 的说明,

1
2
3
4
5
Oncestd::cinis constructed, std::cin.tie() returns &std::cout, 

and likewise, std::wcin.tie() returns &std::wcout.

This means that any formatted input operation onstd::cinforces a call to std::cout.flush() if any characters are pending for output.

cin 被预设绑定了 cout, 被绑定的 ostream 在 istream 输入会被 flush, 标准库提供了 std::cin.tie()设置绑定对象.

说到这了, 顺便说一下 std::endl 这个东西, 可以说等价于 << ‘\n’ << flush, 所做的事情就是清空缓冲区并输出到输出流. 上面说到了 std::cout 会把输出放到一个叫缓冲区(stream buffer) 里, 直到缓冲区满了才会清空缓冲区并把字串输出到 stdout 之类的输出流, 这也就是为什么关闭了缓冲区可能会出现错误. 那么说到这里也就整明白了, 如果频繁使用 std::endl 来做换行输出, 那便是破坏了 std::cout 本身的类似于优化的操作, 也就导致了通常认为 std::cout 的速度比 printf慢.

这也就很好的解释 leetcode 中经常看到的一段加速代码:

1
2
3
4
5
6
static const int _ = [] 
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
return 0;
} ();
script>