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

Многие книги по C++ содержат такой пример кода ...

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

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

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

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

@derobert этот старше другого

Kira 13.11.2013 19:31

@HediNaily действительно так. Но ответ на другой вопрос мне кажется немного лучше, поэтому я решил сделать это таким же образом. Кроме того, другой чуть шире, он также охватывает '\n'.

derobert 13.11.2013 19:35
Payton Millhouse 18.10.2008 01:28
stackoverflow.com/a/30968225/3163618 может быть значительная разница в производительности.
qwr 24.03.2020 07:38
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
595
4
208 879
12
Перейти к ответу Данный вопрос помечен как решенный

Ответы 12

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

И он может выполнять любую другую обработку, которая требуется локальной системе для правильной работы.

dmckee --- ex-moderator kitten 18.10.2008 01:32

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

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

Ответ принят как подходящий

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

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

Или рассмотрите возможность использования ::std::cerr вместо ::std::cout, поскольку он не буферизуется и сбрасывается при каждой операции вывода.

Omnifarious 23.01.2010 14:45

@Omnifarious: std :: cerr не должен быть зарезервирован для ошибок. Два потока не синхронизируются вместе, поэтому, если вы выводите какой-либо текст в cout, он может быть буферизован, и cerr перейдет прямо к выходу, что приведет к отображению смешанного режима. Используйте cerr для того, для чего он должен быть (ошибки), и cout для того, для чего он предназначен (нормальное взаимодействие).

Martin York 03.02.2010 19:39

@ Мартин Йорк, я согласен, ::std::cerr для этого. Но, на мой взгляд, если у вас есть код, в котором вам не нужна буферизация, гораздо более вероятно, что ваш вывод принадлежит ::std::cerr. Я не могу придумать какой-либо веской причины регулярно отказываться от буферизации для ::std::cout.

Omnifarious 04.02.2010 04:29

std :: endl тоже поддерживает платформу, нет?

Lucas 17.02.2010 04:32

@Lucas: Платформа поддерживает не более чем '\ n'.

CB Bailey 17.02.2010 10:39

@LokiAstari: Я бы не сказал, что stderr предназначен для "ошибок". Скорее, это для внеполосных диагностических сообщений, если хотите. Должна быть возможность сказать ./prog > file и сохранить только истинную полезную нагрузку программы, но программа может захотеть вывести гораздо больше информации о состоянии, даже при нормальном взаимодействии.

Kerrek SB 28.11.2011 07:01

«Во многих реализациях стандартный вывод буферизуется по строкам, и запись '\ n' в любом случае вызывает сброс, если не было выполнено std :: cout.sync_with_stdio (false)». скопировано отсюда

GuLearn 14.08.2013 01:01

@Omnifarious, пожалуйста, не помещайте весь свой вывод в cerr. Печать только ошибок в cerr позволяет затем разделить два выходных потока, перенаправив их в разные места. Если я перенаправляю вывод cerr с помощью 2>/dev/null, я не хочу, чтобы весь мой обычный вывод тоже исчезал. Точно так же, если я перенаправляю весь свой обычный вывод в такой файл, как 1>output.txt, я хочу, чтобы весь вывод был без ошибок. Или, если я перенаправляю его на grep или more, я хочу, чтобы канал проталкивал материал cout, как и ожидалось, а затем передавал ошибки, выполняя 3>&1 1>&2 2>&3 | grep. Поэтому, пожалуйста, не смешивайте их. Всегда.

Cory-G 01.07.2014 19:36

@Omnifarious: Хорошая причина регулярно отказываться от буферизации заключается в том, что вы хотите, чтобы ваш вывод был доступен при записи, а не в какое-то неопределенное время в будущем. Но обычно вы хотите, чтобы буферизация происходила, когда вы пишете часть вывода.

user1084944 15.09.2015 19:42

Еще есть ostream :: flush

Braden Best 27.09.2016 02:15

'\ n' также сбрасывается, если вывод подключен к интерактивному устройству, например терминалу.

Emily L. 18.01.2018 17:16

Я вижу, что многие люди говорят «flush», но все, что делает ostream :: flush, - это вызов sync () для нижележащего streambuf, поэтому то, что происходит, полностью зависит от реализации streambuf. Например, fstream использует filebuf, поэтому эффект будет en.cppreference.com/w/cpp/io/basic_filebuf/sync; Также вызов en.cppreference.com/w/cpp/io/ios_base/sync_with_stdio или нет кажется довольно важным, и никто (кроме GuLearn) даже не упоминает об этом: /

Carlo Wood 27.02.2019 13:36

Обратите внимание, что stdout буферизируется только по строкам, если он считается интерактивным, он полностью буферизуется, если не является интерактивным - см. stackoverflow.com/questions/5229096/….

studgeek 25.01.2021 04:51

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

std::cout << std::endl;

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

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

Так,

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

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

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

Во многих случаях «сразу увидеть вывод» - отвлекающий маневр, поскольку cout привязан к cin, а это означает, что если вы читаете ввод от cin, cout будет очищен первым. Но если вы хотите отобразить индикатор выполнения или что-то еще, не читая cin, тогда, конечно, очистка полезна.

Chris Jester-Young 30.03.2011 09:55

@LokiAstari: если вы используете оператор <<, вы, вероятно, не беспокоитесь о производительности - почему? Я не знал, что operator<< не работает, или какую альтернативу использовать для повышения производительности? Пожалуйста, укажите мне какой-нибудь материал, чтобы понять это дальше.

legends2k 22.01.2014 11:33

@ legends2k: Есть старая сказка жен о том, что потоки C++ не так производительны, как printf () в C. Хотя до некоторой степени это правда, основная разница в скорости вызвана тем, что люди неправильно используют потоки C++. stackoverflow.com/a/1042121/14065 В C++ не забудьте отменить синхронизацию iostreams с C-потоками sync_with_stdio(false) и не сбрасывать ваш вывод непрерывно. Пусть библиотека решит, когда это делать. stackoverflow.com/a/1926432/14065

Martin York 22.01.2014 23:53

@Loki: Городская легенда гласит, что sync_with_stdio делает iostreams так же быстро, как stdio. Это не

Ben Voigt 15.09.2015 19:30

@BenVoigt: Я был осторожен со своей формулировкой выше (так что я доволен ими). Он не такой производительный, как stdio (потому что он делает больше). НО Многие люди жалуются на провалы в производительности, вызванные синхронизацией со stdio.

Martin York 15.09.2015 23:43

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

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

(cout<<_1<<"\n")(3); //OK , prints 3

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

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

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

Это может быть очевидно, но это оказывает огромное влияние на многопоточные программы, где, как правило, первая версия будет записывать одну строку в одном кадре, а вторая версия может быть разделена записями из других потоков. Достаточно часто я пишу std :: cout << "hello \ n" << std :: flush, чтобы этого избежать.

smparkes 23.06.2011 03:15

А как насчет std::cout << "Hello" << "\n";?

byxor 22.02.2018 23:39

@byxor Почти то же самое, за исключением очистки буфера, как описано в других ответах. В любом случае, когда вы можете объединить два строковых литерала в один, это будет лишним.

iBug 19.04.2018 09:44

Что ж, если печатаемая строка не является буквальной, тогда вызовов << также будет 2 в случае а, поэтому я бы не стал требовать одного или двух << (или двух вызовов функций в целом). быть разницей между \n и endl.

Enlico 22.11.2018 17:30

Лол, нет, я использую \ n не по этой причине.

Carlo Wood 27.02.2019 13:27

Если вы используете Qt и endl, вы можете случайно использовать неправильный endl, что дает очень удивительные результаты. См. Следующий фрагмент кода:

#include <iostream>
#include <QtCore/QtCore> 
#include <QtGui/QtGui>

// notice that there is no "using namespace std;"
int main(int argc, char** argv)
{
    QApplication qapp(argc,argv);
    QMainWindow mw;
    mw.show();
    std::cout << "Finished Execution!" << endl;
    // This prints something similar to: "Finished Execution!67006AB4"
    return qapp.exec();
}

Обратите внимание, что я написал endl вместо std::endl (что было бы правильно), и, очевидно, есть функция endl, определенная в qtextstream.h (которая является частью QtCore).

Использование "\n" вместо endl полностью обходит любые потенциальные проблемы с пространством имен. Это также хороший пример того, почему размещение символов в глобальном пространстве имен (как это делает Qt по умолчанию) - плохая идея.

Ух! Кому когда-нибудь захочется быть using namespace std; ?? :-)

Steve Folly 17.02.2010 12:55

Противный. Спасибо за комментарий, я уверен, что другие столкнутся с этим.

Head Geek 25.02.2010 04:01

@SteveFolly Я знаю. Почему нет?

ʇolɐǝz ǝɥʇ qoq 21.03.2015 23:44

@ ʇolɐǝzǝɥʇqoq Это нормально, если вы не делаете этого в файлах заголовков.

smerlin 31.03.2015 18:37

@ olɐǝzǝɥʇqoq Пожалуйста, избегайте using namespace std;. Это считается плохой практикой. См. Почему «using namespace std;» считается плохой практикой?

L. F. 22.07.2019 08:57

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

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

ISO/IEC 9899:201x

7.21.3 §7

At program startup, three text streams are predefined and need not be opened explicitly — standard input (for reading conventional input), standard output (for writing conventional output), and standard error (for writing diagnostic output). As initially opened, the standard error stream is not fully buffered; the standard input and standard output streams are fully buffered if and only if the stream can be determined not to refer to an interactive device.

7.21.3 §3

When a stream is unbuffered, characters are intended to appear from the source or at the destination as soon as possible. Otherwise characters may be accumulated and transmitted to or from the host environment as a block. When a stream is fully buffered, characters are intended to be transmitted to or from the host environment as a block when a buffer is filled. When a stream is line buffered, characters are intended to be transmitted to or from the host environment as a block when a new-line character is encountered. Furthermore, characters are intended to be transmitted as a block to the host environment when a buffer is filled, when input is requested on an unbuffered stream, or when input is requested on a line buffered stream that requires the transmission of characters from the host environment. Support for these characteristics is implementation-defined, and may be affected via the setbuf and setvbuf functions.

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

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

С Справка Это манипулятор ввода / вывода только для вывода.

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

Когда использовать:

Этот манипулятор можно использовать для создания строки вывод немедленно,

например

when displaying output from a long-running process, logging activity of multiple threads or logging activity of a program that may crash unexpectedly.

Также

An explicit flush of std::cout is also necessary before a call to std::system, if the spawned process performs any screen I/O. In most other usual interactive I/O scenarios, std::endl is redundant when used with std::cout because any input from std::cin, output to std::cerr, or program termination forces a call to std::cout.flush(). Use of std::endl in place of '\n', encouraged by some sources, may significantly degrade output performance.

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

Это из-за промывки? Я понимаю, как это возможно.

Head Geek 29.10.2018 15:17

@Head В самом деле. Я также видел, как это снижает производительность ввода-вывода диска.

sbi 05.02.2019 18:40

Манипулятор std::endl эквивалентен '\n'. Но std::endl всегда сбрасывает поток.

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

Другие вопросы по теме