Чем отличается endl от n
Перейти к содержимому

Чем отличается endl от n

  • автор:

Различия между ‘\n’ и std::endl

Я знаю, что endl делает перенос и очищает буфер ( flush ). Но почему-то не вижу разницы, что с endl , что с \n , результат один — отображается Hello, world! Как переписать код так, чтобы увидеть разницу с endl и \n ?

Отслеживать
29k 14 14 золотых знаков 61 61 серебряный знак 119 119 бронзовых знаков
задан 29 мая 2016 в 20:07
1,301 5 5 золотых знаков 21 21 серебряный знак 38 38 бронзовых знаков

2 ответа 2

Сортировка: Сброс на вариант по умолчанию

Думаю, что проблема в буферизации вывода.

В C++ потоки ввода и вывода могут быть в одном из трёх состояний: небуферизирован (любой вывод сразу попадает в целевой файл/пайп/на консоль), буферизирован построчно (символы попадают в вывод после окончания каждой строки, исчерпания внутреннего буфера или закрытия потока), и полностью буферизован (символы попадают в вывод лишь после исчерпания внутреннего буфера или закрытия потока).

Майкрософтовская реализация стандартной библиотеки никогда не делает построчную буферизацию (почитайте ответ от Stephan T. Lavavej), имплементации на линуксе обычно делают.

В этом ответе содержится цитата из стандарта (C11 7.21.3 §7):

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

(это относится к чистому C). У C++ та же политика, согласно этому ответу:

C++11 27.4.2 [narrow.stream.objects]/3 : The object cout controls output to a stream buffer associated with the object stdout .

Это означает, что если вывод производится на консоль, а не в файл, то вы увидите всегда полную строчку после \n . А вот если вывод перенаправлен, то произойдёт буферизация.

Вот пример. Рассмотрим код:

#include "stdafx.h" #include #include #include int main()

в MSVC 2015. Если запустить программу обыкновенным образом, мы увидим сначала this is , и лишь через 10 секунд SPARTA . А если запустить программу так: a.exe >x.txt , и заглянуть через пару секунд после запуска в файл x.txt , то вы не увидите там ничего до окончания работы программы.

Если заменить «\n» на std::endl , вывод в файл работает так же, как и на консоль.

Обновление: в MSVC 2015 установить буферизацию std::cout можно вручную (идея с благодарностью украдена подсмотрена в этом ответе):

std::cout.sync_with_stdio(false); char mybuf[1024]; std::cout.rdbuf()->pubsetbuf(mybuf, 1024); std::cout  

Этот код выводит текст только после std::endl .

Какая есть разница между /n и endl?

Все-таки какая-та разница должна же быть, иначе зачем создавать 2 одинаковые функции? Может, типо 1 из них унаследован и т.п. если так то вообще никакой разницы нет что использовать.

  • Вопрос задан более трёх лет назад
  • 6804 просмотра

Комментировать
Решения вопроса 2

\n не везде является переносом строк. endl - более универсальное решение, гарантированно работающее на всех платформах. Кроме того endl зовёт flush, который нужен для гарантированной записи (обычно запись происходит не сразу, а буферизуется).

Ответ написан более трёх лет назад
Нравится 6 1 комментарий

eush77

Если поток открыт в текстовом режиме, то '\n' так же преобразуется в то, во что нужно (можете проверить сами).
Единственная разница — это отсутствие неявного вызова std::flush.

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

eush77

Используйте std::endl тогда и только тогда, когда Вам одновременно нужен и std::flush (например, консольный вывод). В остальных же случаях это может оказаться причиной потери производительности.

Ответ написан более трёх лет назад
Нравится 1 2 комментария

Csklassami

Ivan Ivanov @Csklassami Автор вопроса

@hydragen flush ведет за собой очистку буфера обмена, а какая разница очищу ли его или нет? можете пояснить

eush77

@Csklassami std::flush очищает внутренний буфер стандартной библиотеки. То есть обычно при записи в поток данные не сразу передаются ОС, но накапливаются в буфере и отправляются разом.

Каждое опустошение буфера влечёт за собой системный вызов write(), а системные вызовы замедляют работу программы, поскольку процесс вынужден ожидать ядро ОС.

Размер буфера определяется реализацией, у меня BUFSIZ равен 8192, поэтому предположим, что размер буфера равен 8КБ.
Если программа выводит 64 строки длины ≤128 в поток, и в конце каждой ставит std::endl, то write() будет вызван 64 раза.
Если теперь все ендлы заменить на '\n', то поскольку все строки помещаются в буфер (128⋅64=8192), write() будет вызван только один раз.
Это, должно быть, очень грубый пример, но смысл таков.

Кто быстрее: std::endl или "\n"?

До сегодняшнего дня я свято верил, что в потоках std::endl – это всегда правильнее, чем \n . Переносимость, и все такое. Но, увы.

#include #include int main() for (int i = 0; i  1000000; ++i) std::string s(1, 'x'); std::cout   ::endl; > return 0; > 

Компилируем и запускаем:

clang++ -o endl -O3 endl.cpp && time ./endl >rubbish real 0m4.518s user 0m1.080s sys 0m3.311s 
#include #include int main() for (int i = 0; i  1000000; ++i) std::string s(1, 'x'); std::cout   <'\n'; > return 0; > 

Компилируем и запускаем:

clang++ -o endl -O3 endl.cpp && time ./endl >rubbish real 0m0.263s user 0m0.236s sys 0m0.008s 

std::endl всегда flush ит поток, сбрасывая буфера. \n же просто пихает в поток символ начала новой строки, и большинстве случаев это и требуется. А когда надо, можно отдельно вызвать std::flush , один раз.

Чем отличается endl от n

Чем отличается /n и endl? И то и другое, переносит курсор на следующую строку, так? Тогда в чем разница этих команд? Есть ли случаи, в которых лучше использовать ту или иную команду?

\n - это так называемая "ескейп последовательность".
повстречав этот символ терминал переведет каретку на строчку вниз,
и влево.

то бишь на начало новой строки.

endl - шаблон функции-манипулятора.

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

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

символ '\n' лишь ещё один символ, который уйдёт в поток.
но не факт, что оттуда сразу на терминал.

endl - перевод строки, плюс все содержимое буфера сразу уйдет на терминал.

Сообщение от Stilet

На сколько я понимаю в разных ОС перенос строки разный. endl, думаю, под разные операционки тоже будет подстраиваться в отличии от \n

не правильно понимаете.

на разных ос действительно разные ейскейп последовательности для перевода строки.

однако '\n' - это стандарт. считай что кроссплатформа.

подстроится под целевую платформу - это проблема стандартной библиотеки на этой конкретной целевой платформе.

для пользователей это прозрачно.
можно писать '\n' и не заморачиваться,
во что он там в конечном счете трансформируется на конкретной платформе.

Последний раз редактировалось Stilet; 17.06.2015 в 07:01 .

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *