Почему endl используется как синоним для "\ n", даже если это приводит к значительным потерям производительности? - PullRequest
8 голосов
/ 23 января 2010

Эта программа:

#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 ]

21 голосов
/ 23 января 2010

Я не уверен. Вставка std::endl в выходной поток определяется как эквивалентная вставке .widen('\n') и последующему вызову flush(), и все же многие программисты продолжают использовать std::endl, даже когда нет причин для сброса, например, они сразу переходят к выведите что-нибудь еще.

Я предполагаю, что это исходит из неверного убеждения, что он каким-то образом более переносим, ​​поскольку в нем явно не используется конкретный символ перевода строки. Это неверно, поскольку \n всегда должна отображаться в правильной последовательности новой строки системы для недвоичных файлов потоковой библиотекой.

4 голосов
/ 23 января 2010

Afaik, endl также сбрасывает поток, что может быть причиной снижения производительности.

4 голосов
/ 23 января 2010

Не все так сильно заботятся о производительности. Для некоторых приложений гораздо важнее гарантировать сброс потока.

Редактировать: Кроме того, я считаю endl легче набрать, чем '\n': -)

2 голосов
/ 23 января 2010

Я предполагаю, что учебные тексты используют std::endl с верой в то, что это проще и менее запутанно для начинающих, а впоследствии люди привыкли использовать его.

2 голосов
/ 23 января 2010

Я склонен использовать endl с помощью stringstreams, так как он позволяет легко обнаружить пропущенные разрывы строк.

0 голосов
/ 23 января 2010

На самом деле вопрос в том, почему компилятор сделал такой собачий завтрак из компиляции endl-версии? Если они гарантированно имеют одинаковую семантику, то они также должны иметь одинаковую среду выполнения.

Редактировать: очевидно, я не знал, что Эндл очистил поток ... это то, что вы получаете, не глядя на него.

...