"\n" или '\n' или std:: endl в std:: cout?
Прошло много лет с тех пор, как я перестал использовать std::endl
для завершения строк при записи в std::cout
и вместо этого начал использовать "\n"
.
Но теперь я начинаю видеть больше фрагментов кода, используя '\n'
, и я начал задаваться вопросом, что может быть лучше.
Помимо очевидного, что одна из них является строкой, а другая - символом, есть ли преимущество в использовании этого:
std::cout << variable << '\n';
Через это:
std::cout << variable << "\n";
Позднее добавление:
Когда я задал этот вопрос, мне показалось, что новая строка '\n'
сбросила буфер. Теперь я знаю, что это зависит.
По умолчанию std::cin
привязан к старому stdin
FILE*
, а std::cout
привязан к stdout
. Из-за этой привязки происходит промывка новой строки. По умолчанию stdout
, если подключен к терминалу, буферизируется по строке. Это означает, что новая строка очистит буферы. Поэтому при печати новой строки с использованием std::cout
это приведет к stdout
.
Если stdout
не подключен к терминалу (например, выход был перенаправлен или передан по каналам), или если связь между std::cout
и stdout
нарушена, то символы новой строки ничего не будут скрывать.
Ответы
Ответ 1
Собственно, '\n'
должен быть по умолчанию. Если вы не хотите явно очистить поток (и когда и зачем вы хотите это сделать?), Нет необходимости использовать std::endl
вообще. 1
Конечно, во многих книгах и учебниках по умолчанию используется std::endl
. Это неудачно и может привести к серьезным ошибкам производительности.
Я полагаю, что существует небольшая разница между использованием '\n'
или использованием "\n"
, но последний представляет собой массив из двух символов, который должен быть напечатан символом по символу, для которого необходимо настроить цикл, что более сложно, чем вывод одного символа. Конечно, при выполнении ввода-вывода это редко имеет значение, но если есть сомнения, когда вы хотите вывести один символьный литерал, выведите символьный литерал, а не весь строковый литерал.
Хорошим побочным эффектом этого является то, что вы общаетесь в своем коде, который вы намеревались выводить только один символ, а не просто случайно.
1 Обратите внимание, что std::cout
по умолчанию привязан к std::cin
, что приводит к тому, что std::cout
очищается до любой операции ввода, так что любое приглашение будет перед тем, как пользователь должен что-то ввести.
Ответ 2
Они делают разные вещи. "\n"
Выводит строку новой строки (в соответствующем представлении для конкретной платформы, поэтому она генерирует "\r\n"
в Windows), но std::endl
делает то же самое и очищает поток. Как правило, вам не нужно немедленно очищать поток, и это будет стоить вам самой высокой производительности, поэтому по большей части нет причин использовать std::endl
.
Ответ 3
Нет лучших. Вы используете то, что вам нужно:
- '\n' - для завершения строки
- "some string\n" - конец строки после некоторой строки
-
std::endl
- для завершения строки и очистки потока
Ответ 4
Изменить: я неправильно сформулировал свой ответ, что, возможно, побудило людей поверить, что я думал, что "\n" фактически напечатал нулевой символ. Это, конечно, неправильно:)
Изменить 2: посмотрев ссылку на С++, char
все равно передаются по ссылке, поэтому нет никакой разницы. Единственное отличие состоит в том, что cstring нужно будет искать разделительный символ. Из-за этого неверно.
'\n'
будет настолько немного более эффективным, чем "\n"
, поскольку последний также содержит нулевой символ в конце, что означает, что вы отправляете char*
в operator<<()
(обычно 4 байта на 32-битная система) в отличие от одного байта для char
.
На практике это пограничное значение не имеет значения. Лично я слежу за соглашением, которое изложил Владимир. *
Ответ 5
std::endl
очищает поток. Когда это произойдет, например, потому что вы ожидаете, что ваш вывод станет видимым пользователю своевременно - вы должны использовать std::endl
вместо записи '\n'
в поток (будь то изолированный символ или часть строки).
Иногда вы можете уйти без явного промывания потока самостоятельно; например в среде linux, если cout
синхронизируется с STDOUT
(это значение по умолчанию) и записывается на терминал, то по умолчанию поток будет буферизирован в строке и будет автоматически очищаться каждый раз, когда вы пишете новую строку.
Однако рискованно полагаться на это поведение. например в той же среде linux, если вы решите запустить свою программу с STDOUT
, перенаправленной в файл или переданной на другой процесс, тогда по умолчанию поток будет буферизироваться в блоке.
Аналогичным образом, если позже вы решите отключить синхронизацию с stdio (например, для эффективности), тогда реализации будут использовать механизмы буферизации iostream
, которые не имеют режима буферизации строк.
Я видел много потерянной производительности из-за этой ошибки; если вывод должен быть видимым, когда он написан, то вы должны явно использовать std::endl
(или использовать std::flush
или std::ostream::flush
, но я обычно нахожу std::endl
более удобным), или делать что-то еще, что обеспечивает частое удаление достаточно, например, конфигурирование STDOUT
для буферизации строк (при условии, что это соответствует).
Ответ 6
-
std::cout << variable << std::endl;
std::endl
выводит новую строку, но также очищает выходной поток. Другими словами, тот же эффект, что и
std::cout << variable << '\n'; // output newline
std::cout.flush(); // then flush
-
std::cout << variable << '\n';
'\n'
выводит новую строку для char,
, поэтому ostream& operator<< (ostream& os, char c);
будет использоваться.
-
std::cout << variable << "\n";
"\n"
является const char[2]
, поэтому ostream& operator<< (ostream& os, const char* s);
будет использоваться. Мы можем себе представить, что эта функция будет содержать цикл, мы можем утверждать, что это излишне, чтобы просто распечатать новую строку.