"\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); будет использоваться. Мы можем себе представить, что эта функция будет содержать цикл, мы можем утверждать, что это излишне, чтобы просто распечатать новую строку.