Многие книги по C++ содержат такой пример кода ...
std::cout << "Test line" << std::endl;
... так что я тоже всегда так поступал. Но вместо этого я видел много такого кода от работающих разработчиков:
std::cout << "Test line\n";
Есть ли техническая причина предпочесть одно другому или это просто вопрос стиля кодирования?
@HediNaily действительно так. Но ответ на другой вопрос мне кажется немного лучше, поэтому я решил сделать это таким же образом. Кроме того, другой чуть шире, он также охватывает '\n'.
Хорошее объяснение: cppkid.wordpress.com/2008/08/27/why-i-prefer-n-to-stdendl





Могут быть проблемы с производительностью, std::endl принудительно очищает выходной поток.
И он может выполнять любую другую обработку, которая требуется локальной системе для правильной работы.
Оба они напишут соответствующий символ (символы) конца строки. В дополнение к этому endl вызовет фиксацию буфера. Обычно вы не хотите использовать endl при выполнении файлового ввода-вывода, потому что ненужные коммиты могут повлиять на производительность.
У меня всегда была привычка использовать просто std :: endl, потому что мне это легко увидеть.
Различные символы конца строки не имеют значения, если файл открыт в текстовом режиме, что вы и получите, если не попросите двоичный файл. Скомпилированная программа напишет то, что нужно для компилируемой системы.
Единственная разница в том, что std::endl очищает выходной буфер, а '\n' - нет. Если вы не хотите, чтобы буфер часто очищался, используйте '\n'. Если да (например, если вы хотите получить весь вывод, а программа работает нестабильно), используйте std::endl.
Или рассмотрите возможность использования ::std::cerr вместо ::std::cout, поскольку он не буферизуется и сбрасывается при каждой операции вывода.
@Omnifarious: std :: cerr не должен быть зарезервирован для ошибок. Два потока не синхронизируются вместе, поэтому, если вы выводите какой-либо текст в cout, он может быть буферизован, и cerr перейдет прямо к выходу, что приведет к отображению смешанного режима. Используйте cerr для того, для чего он должен быть (ошибки), и cout для того, для чего он предназначен (нормальное взаимодействие).
@ Мартин Йорк, я согласен, ::std::cerr для этого. Но, на мой взгляд, если у вас есть код, в котором вам не нужна буферизация, гораздо более вероятно, что ваш вывод принадлежит ::std::cerr. Я не могу придумать какой-либо веской причины регулярно отказываться от буферизации для ::std::cout.
std :: endl тоже поддерживает платформу, нет?
@Lucas: Платформа поддерживает не более чем '\ n'.
@LokiAstari: Я бы не сказал, что stderr предназначен для "ошибок". Скорее, это для внеполосных диагностических сообщений, если хотите. Должна быть возможность сказать ./prog > file и сохранить только истинную полезную нагрузку программы, но программа может захотеть вывести гораздо больше информации о состоянии, даже при нормальном взаимодействии.
«Во многих реализациях стандартный вывод буферизуется по строкам, и запись '\ n' в любом случае вызывает сброс, если не было выполнено std :: cout.sync_with_stdio (false)». скопировано отсюда
@Omnifarious, пожалуйста, не помещайте весь свой вывод в cerr. Печать только ошибок в cerr позволяет затем разделить два выходных потока, перенаправив их в разные места. Если я перенаправляю вывод cerr с помощью 2>/dev/null, я не хочу, чтобы весь мой обычный вывод тоже исчезал. Точно так же, если я перенаправляю весь свой обычный вывод в такой файл, как 1>output.txt, я хочу, чтобы весь вывод был без ошибок. Или, если я перенаправляю его на grep или more, я хочу, чтобы канал проталкивал материал cout, как и ожидалось, а затем передавал ошибки, выполняя 3>&1 1>&2 2>&3 | grep. Поэтому, пожалуйста, не смешивайте их. Всегда.
@Omnifarious: Хорошая причина регулярно отказываться от буферизации заключается в том, что вы хотите, чтобы ваш вывод был доступен при записи, а не в какое-то неопределенное время в будущем. Но обычно вы хотите, чтобы буферизация происходила, когда вы пишете часть вывода.
Еще есть ostream :: flush
'\ n' также сбрасывается, если вывод подключен к интерактивному устройству, например терминалу.
Я вижу, что многие люди говорят «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) даже не упоминает об этом: /
Обратите внимание, что stdout буферизируется только по строкам, если он считается интерактивным, он полностью буферизуется, если не является интерактивным - см. stackoverflow.com/questions/5229096/….
Разницу можно проиллюстрировать следующим:
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, тогда, конечно, очистка полезна.
@LokiAstari: если вы используете оператор <<, вы, вероятно, не беспокоитесь о производительности - почему? Я не знал, что operator<< не работает, или какую альтернативу использовать для повышения производительности? Пожалуйста, укажите мне какой-нибудь материал, чтобы понять это дальше.
@ legends2k: Есть старая сказка жен о том, что потоки C++ не так производительны, как printf () в C. Хотя до некоторой степени это правда, основная разница в скорости вызвана тем, что люди неправильно используют потоки C++. stackoverflow.com/a/1042121/14065 В C++ не забудьте отменить синхронизацию iostreams с C-потоками sync_with_stdio(false) и не сбрасывать ваш вывод непрерывно. Пусть библиотека решит, когда это делать. stackoverflow.com/a/1926432/14065
@Loki: Городская легенда гласит, что sync_with_stdio делает iostreams так же быстро, как stdio. Это не
@BenVoigt: Я был осторожен со своей формулировкой выше (так что я доволен ими). Он не такой производительный, как stdio (потому что он делает больше). НО Многие люди жалуются на провалы в производительности, вызванные синхронизацией со stdio.
Ничего страшного, но 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, чтобы этого избежать.
А как насчет std::cout << "Hello" << "\n";?
@byxor Почти то же самое, за исключением очистки буфера, как описано в других ответах. В любом случае, когда вы можете объединить два строковых литерала в один, это будет лишним.
Что ж, если печатаемая строка не является буквальной, тогда вызовов << также будет 2 в случае а, поэтому я бы не стал требовать одного или двух << (или двух вызовов функций в целом). быть разницей между \n и endl.
Лол, нет, я использую \ n не по этой причине.
Если вы используете 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; ?? :-)
Противный. Спасибо за комментарий, я уверен, что другие столкнутся с этим.
@SteveFolly Я знаю. Почему нет?
@ ʇolɐǝzǝɥʇqoq Это нормально, если вы не делаете этого в файлах заголовков.
@ olɐǝzǝɥʇqoq Пожалуйста, избегайте using namespace std;. Это считается плохой практикой. См. Почему «using namespace std;» считается плохой практикой?
Я вспомнил, что читал об этом в стандарте, так вот:
См. Стандарт 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 В самом деле. Я также видел, как это снижает производительность ввода-вывода диска.
Манипулятор std::endl эквивалентен '\n'. Но std::endl всегда сбрасывает поток.
std::cout << "Test line" << std::endl; // with flush
std::cout << "Test line\n"; // no flush
@derobert этот старше другого