C ++: "std :: endl" против "\ n" - PullRequest
       83

C ++: "std :: endl" против "\ n"

497 голосов
/ 18 октября 2008

Многие книги на C ++ содержат пример кода, подобного этому ...

std::cout << "Test line" << std::endl;

... так что я всегда так делал. Но вместо этого я видел много кода от таких разработчиков:

std::cout << "Test line\n";

Есть ли техническая причина, чтобы отдавать предпочтение одному над другим, или это просто вопрос стиля кодирования?

Ответы [ 13 ]

422 голосов
/ 18 октября 2008

Различные символы конца строки не имеют значения, при условии, что файл открыт в текстовом режиме, что вы и получите, если не спросите двоичный файл. Скомпилированная программа выпишет правильную вещь для системы, скомпилированной для.

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

214 голосов
/ 18 октября 2008

Разница может быть проиллюстрирована следующим:

std::cout << std::endl;

эквивалентно

std::cout << '\n' << std::flush;

Итак,

  • Используйте std::endl Если вы хотите принудительно произвести немедленный сброс к выходу.
  • Используйте \n, если вы беспокоитесь о производительности (что, вероятно, не так, если вы используете оператор <<).

Я использую \n в большинстве строк.
Затем используйте std::endl в конце абзаца (но это просто привычка и обычно не требуется).

В отличие от других утверждений, символ \n сопоставляется с правильным концом строки платформы, только если поток идет в файл (std::cin и std::cout являются специальными, но все еще файлами (или файловыми )).

40 голосов
/ 18 октября 2008

Возможны проблемы с производительностью, std::endl вызывает сброс потока вывода.

26 голосов
/ 29 августа 2014

Я вспомнил, что читал об этом в стандарте, так что вот так:

См. Стандарт C11, который определяет, как ведут себя стандартные потоки, поскольку программы C ++ взаимодействуют с CRT, стандарт C11 должен регулировать политику очистки здесь.

ISO / IEC 9899: 201x

7.21.3 §7

При запуске программы три текстовых потока предопределены и не требуют явного открытия - стандартный ввод (для чтения обычного ввода), стандартный вывод (для записи условный вывод) и стандартная ошибка (для записи диагностического вывода). Как изначально открыт, стандартный поток ошибок не полностью буферизован; стандартный ввод и стандарт выходные потоки полностью буферизуются тогда и только тогда, когда можно определить, что поток не относится к на интерактивное устройство.

7.21.3 §3

Когда поток небуферизован, символы должны появляться из источника или на пункт назначения как можно скорее. В противном случае символы могут быть накоплены и передается в или из среды хоста в виде блока. Когда поток полностью буферизован, символы предназначены для передачи в или из среды хоста как блок, когда буфер заполнен. Когда поток буферизуется в строке, символы должны быть передается в или из среды хоста как блок, когда символ новой строки встречается. Кроме того, символы предназначены для передачи в качестве блока на хост окружение, когда буфер заполнен, когда ввод запрашивается в небуферизованном потоке, или когда ввод запрашивается в потоке с буферизацией строки, который требует передачи персонажи из среды хоста. Поддержка этих характеристик определяется реализацией и может зависеть от функций setbuf и setvbuf. * ​​1014 *

Это означает, что std::cout и std::cin полностью буферизированы тогда и только тогда, когда относятся к неинтерактивному устройству. Другими словами, если stdout подключен к терминалу, то нет различий в поведении.

Однако, если вызывается std::cout.sync_with_stdio(false), то '\n' не вызовет сброс даже для интерактивных устройств. В противном случае '\n' эквивалентно std::endl, за исключением случаев, когда выполняется конвейеризация файлов: c ++ ref для std :: endl .

23 голосов
/ 18 ноября 2009

Там есть еще один вызов функции, если вы собираетесь использовать std::endl

a) std::cout << "Hello\n";
b) std::cout << "Hello" << std::endl;

а) звонит оператору << один раз.
б) звонит оператору << дважды.

18 голосов
/ 18 октября 2008

Они оба напишут соответствующие символы конца строки. В дополнение к этому endl приведет к тому, что буфер будет зафиксирован. Обычно вы не хотите использовать endl при выполнении файлового ввода-вывода, потому что ненужные коммиты могут повлиять на производительность.

11 голосов
/ 22 февраля 2009

Ничего страшного, но endl не будет работать в boost :: lambda .

(cout<<_1<<endl)(3); //error

(cout<<_1<<"\n")(3); //OK , prints 3
9 голосов
/ 17 февраля 2010

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

#include <iostream>
#include <QtCore/QtCore> 
#include <QtGui/QtGui>
//notice that i dont have a "using namespace std;"
int main(int argc, char** argv)
{
    QApplication qapp(argc,argv);
    QMainWindow mw;
    mw.show();
    std::cout << "Finished Execution !" << endl << "...";
    // Line above printed: "Finished Execution !67006AB4..."
    return qapp.exec();
}

Конечно, это была моя ошибка, так как я должен был написать std::endl, , но если вы используете endl, qt и using namespace std;, это зависит от порядка включаемых файлов, если правильный endl будет использоваться. *

Конечно, вы можете перекомпилировать Qt для использования пространства имен, поэтому вы получите ошибку компиляции для примера выше.

РЕДАКТИРОВАТЬ: Забыл упомянуть, Qt endl объявлен в "qtextstream.h", который является частью QtCore

* EDIT2: C ++ выберет правильный endl, если у вас есть using для std::cout или пространство имен std, так как std::endl находится в том же пространстве имен, что и std::cout, механизм C ++ ADL будет выбрать std::endl.

2 голосов
/ 18 октября 2008

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

0 голосов
/ 24 мая 2019

Манипулятор endl эквивалентен '\'. Но endl всегда очищает поток.

std::cout << "Test line" << std::endl; // with flush
std::cout << "Test line\n"; // no flush
...