为什么endl被用作“\ n”的同义词,即使它会导致严重的性能损失?

时间:2010-01-23 11:35:58

标签: c++ performance iostream

这个程序:

#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'?的同义词

编辑:如果不明显,此问题旨在成为一个主要问题,并且出于教学目的。我知道为什么存在性能损失。

6 个答案:

答案 0 :(得分:21)

我不确定。将std::endl插入输出流定义为等同于插入.widen('\n')然后调用flush(),然而许多程序员仍然坚持使用std::endl,即使没有理由进行刷新例如,他们继续立即输出其他东西。

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

答案 1 :(得分:4)

并非所有人都非常关心性能。对于某些应用程序,保证流被刷新更为重要。

修改:此外,我发现endl'\n'更容易打字: - )

答案 2 :(得分:4)

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

答案 3 :(得分:2)

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

答案 4 :(得分:2)

我的猜测是,教学文本使用std::endl,认为它对初学者来说更简单,更少混淆,之后人们习惯于使用它。

答案 5 :(得分:0)

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

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