代码之家  ›  专栏  ›  技术社区  ›  Omnifarious

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

  •  8
  • Omnifarious  · 技术社区  · 16 年前

    这个程序:

    #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 回复  |  直到 15 年前
        1
  •  21
  •   Omnifarious    16 年前

    我不确定。插入 std::endl 在输出流中定义为等同于插入 .widen('\n') 然后打电话 flush() 但是许多程序员坚持使用 标准::结束 即使没有原因进行刷新,例如,它们也会立即输出其他内容。

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

        2
  •  4
  •   helpermethod    16 年前

    afaik,endl也会刷新流,这可能是性能损失的原因。

        3
  •  4
  •   anon    16 年前

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

    编辑: 而且,我发现 endl 打字比 '\n' -)

        4
  •  2
  •   josefx    16 年前

    我倾向于在stringstream上使用endl with,因为它可以很容易地发现缺少的换行符。

        5
  •  2
  •   jamesdlin    16 年前

    我猜是教学课本使用的 std::endl 相信它对初学者来说更简单、更容易混淆,之后人们就习惯了使用它。

        6
  •  0
  •   Andrew McGregor    16 年前

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

    编辑:很明显,我不知道Endl冲洗了这条小溪……这就是你不查的原因。