Вопрос

Многие книги по 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 " аналогично нажатию клавиши ВВОД + ПРОБЕЛ.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top