endl и промывка буфера

на C++ primer книга, в главе (1), она упоминает следующее:

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

Что означает "промывка буфера" здесь?

5 ответов


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

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


iostreams C++буферизованы, это означает, что при выходе в поток содержимое не будет сразу переходить к тому, что находится за потоком, например, stdout в случае cout. Реализация потока определяет, когда фактически отправлять буферизованную часть потока. Это делается по соображениям эффективности, было бы очень неэффективно записывать в сеть или дисковый поток байт за байтом, путем буферизации эта проблема решена.

Это, однако, означает, что когда вы пишете сообщения отладки в файл журнала, и ваша программа аварийно завершает работу, вы можете потерять часть данных, записанных в файл журнала через поток, поскольку часть журнала все еще может быть в буфере потока и еще не записана в фактический файл. Чтобы этого не произошло, вам нужно сделать поток flush его буферов либо явным вызовом метода flush, либо с помощью удобства endl.

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

отредактировано, чтобы включить это примечание:

cin и cout имеют особенное отношение, где чтение от cin автоматически потопит cout заранее. Это гарантирует, что, например, запрос писал в cout будет видеть пользователь до чтения из Cin ждет ввода. Следовательно, даже в cout вам обычно не нужен endl, но вместо этого вы можете использовать \n. Вы можете создать такие отношения между другими потоками также связывают их вместе.


что подразумевается под" промывкой буфера " здесь?

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

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


Справочная информация

ввод-вывод вычислительной системы, как правило, очень сложный и состоит из нескольких слоев абстракции. Каждый такой слой может ввести определенное количество накладных расходов. Буферизация данных-это способ уменьшить эти накладные расходы путем минимизации количества отдельных транзакций, выполняемых между двумя уровнями системы.

  • буферизация (кэширование) на уровне процессора/памяти: для очень высокой активности даже система произвольного доступа к памяти компьютера может стать узким местом. Чтобы решить эту проблему, CPU виртуализирует память доступ, предоставляя многослойные слои скрытых кэшей (отдельные буферы которых называются линиями кэша). Эти процессорные кэши буферизуют память вашего алгоритма (в соответствии с написание политики) для минимизации избыточных обращений на шине памяти.

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

  • буферизация библиотеки ввода-вывода: элемент в C++ ИО трансляцию библиотека дополнительно управляет буфером для каждого открытого потока. Этот буфер используется, в частности, для ограничения числа .

  • Метод 2: Не используйте std::endl -- использовать что-то вроде следующей версии вместо...

inline std::ostream & endl( std::ostream & os )
   {
   os.put( os.widen('\n') ); // http://en.cppreference.com/w/cpp/io/manip/endl
   if ( debug_mode ) os.flush(); // supply 'debug_mode' however you want
   return os;
   }

в этом примере, вы обеспечиваете таможни endl который можно вызвать С-или-без вызова внутреннего вызова flush() (что и заставляет переходить на операционную систему). Включение Флеша (с помощью debug_mode переменная) полезна для отладки сценариев, где вы хотите иметь возможность просматривать выходные данные (например, диск-файл) , когда программа завершилась перед чистым закрытием связанные потоки (которые бы принудительно завершили промывку буфера).


при использовании std::cout операнд после оператора вывода ( << ) хранятся в буфере и не отображаются на stdin (обычно терминал или командная строка), пока не встретится std::endl или std::cin, что приводит к буферу вспыхнул в смысле, выводить/вывести содержимое буфера на stdin.

считайте эту программу:

#include <iostream>
#include <unistd.h>

int main(void)
{
    std::cout << "Hello, world";
    sleep(2);
    std::cout << std::endl;

    return 0;
}

полученный результат будет:

после 2 секунды

Привет, Мир


один простой код, чтобы показать вам эффекты буферизованного ввода/вывода в C++

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

посмотрите на код ниже: // программа для проверки того, как буферизованный ввод-вывод может непреднамеренно влиять на нашу программу #включать с помощью пространства имен std;

int main()
{
    int a;
    char c;
    cin>>a;
    cin>>c;
    cout<<"the number is : "<<a;
    cout<<"\nthe character is : "<<c;

}

здесь мы объявили две переменные one int и one char если мы введем число как " 12d34" это вызовет переменная int принимает только 12 в качестве значения, и она отбрасывает остальные, которые все еще будут в буфере. И на следующем входе переменная char автоматически примет значение " d" даже не спрашивая вас о каком-либо входе