"std::endl" против "\n": в чем разница?"
Проблема с выводом в C++
Во многих книгах по C++ содержатся примеры кода в следующем виде:
std::cout << "Test line" << std::endl;
Поэтому я всегда использовал именно этот вариант. Однако я заметил, что многие практикующие разработчики предпочитают другой подход:
std::cout << "Test line\n";
Существует ли техническая причина предпочитать один из этих вариантов, или это просто вопрос стиля программирования?
5 ответ(ов)
Разница может быть проиллюстрирована следующим образом:
std::cout << std::endl;
эквивалентно
std::cout << '\n' << std::flush;
Итак,
- Используйте
std::endl
, если хотите принудительно выполнить немедленное сбрасывание буфера вывода. - Используйте
\n
, если вас беспокоит производительность (что, вероятно, не столь актуально, если вы используете оператор<<
).
Я использую \n
в большинстве случаев.
А затем применяю std::endl
в конце абзаца (но это просто привычка и обычно не обязательно).
Вопреки другим утверждениям, символ \n
отображается (или преобразуется) в правильную последовательность конца строки платформы только если поток является текстовым файловым потоком, включая std::cout
(и std::cin
). Преобразование не происходит для бинарных файловых потоков или других типов потоков, таких как std::stringstream
.
Возможно, возникнут проблемы с производительностью, так как std::endl
принудительно сбрасывает буфер выходного потока.
Если вы используете std::endl
, это подразумевает ещё один вызов функции. Рассмотрим оба примера:
a) std::cout << "Hello\n";
b) std::cout << "Hello" << std::endl;
В первом примере (a) оператор <<
вызывается один раз. Он отправляет строку "Hello" и символ новой строки \n
в стандартный вывод.
Во втором примере (b) оператор <<
вызывается дважды. Сначала он отправляет строку "Hello" в стандартный вывод, а затем вызывается второй раз для std::endl
, который дополнительно отправляет символ конца строки и очищает буфер вывода.
Таким образом, в случае (b) происходит больше работы из-за дополнительного вызова std::endl
.
Оба варианта будут записывать соответствующий символ(ы) конца строки. Однако, добавitionally, использование endl
приведет к сбросу буфера. Обычно не рекомендуется использовать endl
при работе с файловым вводом/выводом, поскольку лишние сбросы могут негативно сказаться на производительности.
Если вы используете Qt и endl
, вы можете случайно столкнуться с использованием неправильного endl
, что приведет к достаточно неожиданным результатам. Посмотрите на следующий фрагмент кода:
#include <iostream>
#include <QtCore/QtCore>
#include <QtGui/QtGui>
// обратите внимание, что здесь нет "using namespace std;"
int main(int argc, char** argv)
{
QApplication qapp(argc,argv);
QMainWindow mw;
mw.show();
std::cout << "Завершение выполнения!" << endl;
// Это выводит что-то подобное: "Завершение выполнения!67006AB4"
return qapp.exec();
}
Обратите внимание, что я написал endl
вместо std::endl
(что было бы правильно), и оказывается, что в qtextstream.h (который является частью QtCore) определена функция endl
.
Использование "\n"
вместо endl
полностью исключает любые потенциальные проблемы с пространствами имен. Это также хороший пример того, почему помещать символы в глобальное пространство имен (как это делает Qt по умолчанию) — плохая идея.
Что такое Правило трёх?
Разница между const int*, const int * const и int * const?
Почему следует использовать указатель вместо самого объекта?
Имеют ли круглые скобки после имени типа значение при использовании new?
`std::wstring` против `std::string`: когда использовать и в чем разница?