C++:“std::endl” против “ ”
-
03-07-2019 - |
Вопрос
Многие книги по C ++ содержат примеры кода, подобные этому...
std::cout << "Test line" << std::endl;
..так что я тоже всегда так делал.Но вместо этого я видел много кода от работающих разработчиков, подобных этому:
std::cout << "Test line\n";
Есть ли техническая причина предпочесть одно другому, или это просто вопрос стиля кодирования?
Решение
Различные символы конца строки не имеют значения, при условии, что файл открыт в текстовом режиме, что вы и получите, если не спросите двоичный файл. Скомпилированная программа выпишет правильную вещь для системы, для которой скомпилировано.
Единственное отличие состоит в том, что std :: endl
очищает выходной буфер, а '\ n'
- нет. Если вы не хотите, чтобы буфер часто очищался, используйте '\ n'
. Если вы это сделаете (например, если вы хотите получить все выходные данные, а программа работает нестабильно), используйте std :: endl
.
Другие советы
Разницу можно проиллюстрировать следующим образом:
std::cout << std::endl;
эквивалентно
std::cout << '\n' << std::flush;
Итак,
- Использование
std::endl
Если вы хотите принудительно выполнить немедленную очистку выходных данных. - Использование
\n
если вы беспокоитесь о производительности (что, вероятно, не так, если вы используете<<
оператор).
Я использую \n
по большинству линий.
Затем используйте std::endl
в конце абзаца (но это просто привычка и обычно в этом нет необходимости).
Вопреки другим утверждениям, \n
символ сопоставляется с правильной последовательностью конца строки платформы только в том случае, если поток направляется в файл (std::cin
и std::cout
будучи особенными, но все же файлами (или файлоподобными)).
Возможны проблемы с производительностью, std :: endl
вызывает сброс потока вывода.
Я вспомнил, что читал об этом в стандарте, так что вот так:
См. стандарт C11, который определяет, как ведут себя стандартные потоки, поскольку программы C ++ взаимодействуют с CRT, стандарт C11 должен регулировать политику очистки здесь.
ISO / IEC 9899: 201x
7.21.3 & # 167; 7
При запуске программы три текстовых потока предопределены и не требуют явного открытия & # 8212; стандартный ввод (для чтения обычного ввода), стандартный вывод (для записи условный вывод) и стандартная ошибка (для записи диагностического вывода). Как изначально открыт, стандартный поток ошибок не полностью буферизован; стандартный ввод и стандарт выходные потоки полностью буферизуются тогда и только тогда, когда можно определить, что поток не относится к на интерактивное устройство.
7.21.3 & # 167; 3
Когда поток небуферизован, символы должны появляться из источника или на пункт назначения как можно скорее. В противном случае символы могут быть накоплены и передается в или из среды хоста в виде блока. Когда поток полностью буферизован, символы предназначены для передачи в или из среды хоста как блок, когда буфер заполнен. Когда поток буферизуется в строке, символы должны быть передается в или из среды хоста как блок, когда символ новой строки встречается. Кроме того, символы предназначены для передачи в качестве блока на хост окружение, когда буфер заполнен, когда ввод запрашивается в небуферизованном потоке, или когда ввод запрашивается в потоке с буферизацией строки, который требует передачи персонажи из среды хоста. Поддержка этих характеристик определяется реализацией и может зависеть от функций setbuf и setvbuf.
Это означает, что std :: cout
и std :: cin
полностью буферизованы тогда и только тогда, когда ссылаются на не интерактивное устройство. Другими словами, если stdout подключен к терминалу, то нет различий в поведении. Р>
Однако, если std :: cout.sync_with_stdio (false)
вызван, то '\ n'
не вызовет сброс даже для интерактивных устройств. В противном случае '\ n'
эквивалентно std :: endl
, если только не осуществляется передача в файлы: c ++ ref для std :: endl .
Там есть еще один вызов функции, если вы собираетесь использовать std :: endl
a) std::cout << "Hello\n";
b) std::cout << "Hello" << std::endl;
a) вызывает оператор < <
один раз.
б) дважды вызывает оператора <
.
Они оба напишут соответствующие символы конца строки. В дополнение к этому endl приведет к тому, что буфер будет зафиксирован. Обычно вы не хотите использовать endl при выполнении файлового ввода-вывода, потому что ненужные коммиты могут повлиять на производительность.
Ничего страшного, но endl не будет работать в boost :: lambda .
(cout<<_1<<endl)(3); //error
(cout<<_1<<"\n")(3); //OK , prints 3
Если вы используете 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 и , используя пространство имен std;
зависит от порядка включаемых файлов, если будет использоваться правильный endl
.
Конечно, вы можете перекомпилировать Qt для использования пространства имен, поэтому вы получите ошибку компиляции для приведенного выше примера.
РЕДАКТИРОВАТЬ: Забыл упомянуть, что endl
в Qt объявлен в " qtextstream.h " который является частью QtCore
* EDIT2: C ++ выберет правильный endl
, если у вас есть using
для std :: cout
или пространства имен std
, поскольку std :: endl
находится в том же пространстве имен, что и std :: cout
, механизм C ++ ADL выберет std :: endl
. р>
У меня всегда была привычка просто использовать std :: endl, потому что мне легко это видеть.
С ссылка Это важный момент манипулятор ввода-вывода только для вывода.
std::endl
Вставляет символ новой строки в выходную последовательность os и сбрасывает его, как будто вызывая os.put(os.widen('\n'))
за которым следует os.flush()
.
Когда использовать:
Этот манипулятор может быть использован для создания линии выводите немедленно,
например ,
при отображении выходных данных длительно выполняющегося процесса, протоколировании активности нескольких потоков или протоколировании активности программы, которая может неожиданно завершиться сбоем.
Также
Явная очистка std::cout также необходима перед вызовом std::system, если созданный процесс выполняет какой-либо экранный ввод-вывод.В большинстве других обычных сценариев интерактивного ввода-вывода std::endl является избыточным при использовании с std::cout, потому что любой ввод из std::cin, вывод в std :: cerr или завершение программы вызывает вызов std ::cout .промывка ().Использование std::endl вместо '\ n', поощряемое некоторыми источниками, может значительно снизить производительность вывода.
Если вы намереваетесь запустить свою программу на чем-то другом, кроме вашего ноутбука, никогда не используйте оператор endl
. Особенно, если вы пишете много коротких строк или, как я часто видел, отдельные символы в файле. Известно, что использование endl
убивает сетевые файловые системы, такие как NFS.
Манипулятор endl
эквивалентен '\'
. Но endl
всегда очищает поток. Р>
std::cout << "Test line" << std::endl; // with flush
std::cout << "Test line\n"; // no flush
Если вы не заметили, endl
похоже на нажатие клавиши ВВОД, а " \ n "
аналогично нажатию клавиши ВВОД + ПРОБЕЛ.