8

这个程序:

#include <iostream>
#include <cstdlib>
#include <string>

int main(int argc, const char *argv[])
{
   using ::std::cerr;
   using ::std::cout;
   using ::std::endl;

   if (argc < 2 || argc > 3) {
      cerr << "Usage: " << argv[0] << " [<count>] <message>\n";
      return 1;
   }
   unsigned long count = 10000;
   if (argc > 2) {
      char *endptr = 0;
      count = ::std::strtoul(argv[1], &endptr, 10);
      if ((argv[1][0] == '\0') || (*endptr != '\0')) {
         cerr << "Usage: " << argv[0] << " [<count>] <message>\n";
         return 1;
      }
   }
   const ::std::string msg((argc < 3) ? argv[1] : argv[2]);
   for (unsigned long i = 0; i < count; ++i) {
      cout << i << ": " << msg << '\n';
   }
   return 0;
}

当时间像这样:

$ time ./joe 10000000 fred >/dev/null

real  0m15.410s
user  0m10.551s
sys   0m0.166s

执行需要 15.4 秒的实时时间。用这个替换输出行:cout << i << ": " << msg << endl;你最终会得到这样的结果:

$ time ./joe 10000000 fred >/dev/null

real  0m39.115s
user  0m16.482s
sys   0m15.803s

如您所见,运行时间增加了一倍多,程序从在操作系统中花费的时间最少到在操作系统中花费了将近一半的时间。

该程序的两个版本具有相同的输出,并且由标准保证在每个平台上具有相同的输出。

鉴于此,为什么人们坚持使用endl作为同义词'\n'?

编辑: 如果不是很明显,这个问题旨在成为一个引导性问题,并用于教学目的。我知道为什么存在性能损失。

4

6 回答 6

21

我不确定。插入std::endl输出流被定义为等同于插入.widen('\n')然后调用flush(),但许多程序员std::endl即使在没有理由刷新的情况下仍坚持使用,例如他们继续立即输出其他内容。

我的假设是它来自一个错误的信念,即它在某种程度上更便携,因为它没有明确使用特定的换行符。这是不正确\n的,因为流库必须始终将非二进制文件映射到系统的正确换行符序列。

于 2010-01-23T11:43:16.927 回答
4

不是每个人都那么关心性能。对于某些应用程序,确保流被刷新更为重要。

编辑:另外,我发现endl比输入更容易'\n':-)

于 2010-01-23T11:39:28.153 回答
4

Afaik,endl 也会刷新流,这可能是性能下降的原因。

于 2010-01-23T11:39:30.770 回答
2

我倾向于在 stringstreams 上使用 endl,因为它可以很容易地发现丢失的换行符。

于 2010-01-23T12:08:33.533 回答
2

My guess is that instructional texts use std::endl with the belief that it's simpler and less confusing for beginners, and afterward people got accustomed to using it.

于 2010-01-23T12:44:03.273 回答
0

真正的问题是,为什么编译器会为编译 endl 版本做这样的狗早餐?如果保证它们具有相同的语义,那么它们也应该具有相同的运行时。

编辑:显然,我不知道 endl 刷新了流......这就是你不查找它的结果。

于 2010-01-23T11:38:55.453 回答