Вопрос по c++ – Буферизованный и небуферизованный поток

3

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

<code>cout << "hi"; 
</code>

What do they mean by "the buffer is full".

<code>cerr << "hi";
</code>

It is said in my book that everything sent to cerr is written to the standard error device immediately, what does it mean?

<code>char *ch;
cin>> ch; // I typed "hello world";
</code>

In this example ch will be assigned to "hello" and "world" will be ignored does it mean that it still in the buffer and it will affect the results of future statements?

Фактически, во втором примере вы будете записывать в память в неизвестном месте и вызывать неопределенное поведение ... ** надеюсь **, что приведет к падению. Crazy Eddie
Стандартное примечание: по умолчаниюcout синхронизируется сstdioи по умолчаниюstdio является буферизованной строкой. ybungalobill

Ваш Ответ

5   ответов
10

1) Выходные потоки отправляют свои байтыstd::streambuf, который может содержать буфер;std::filebuf (происходит отstreambuf) использован а такжеstd::ofstream как правило, буферизуется. Это означает, что когда вы выводите символ, он не обязательно выводится сразу; будет записываться в буфер и выводиться в ОС только тогда, когда буфер полный, или вы явно запрашиваете его каким-либо образом, как правило, вызывая flush() в потоке (прямо или косвенно, используяstd::endl). This can vary, however; output to std::cout синхронизируется с stdoutи большинство реализаций будут более или менее следовать правилам stdout заstd::coutизменение стратегии буферизации, если вывод собирается на интерактивное устройство.

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

2) Ваша книга здесь не права.

Одна из стратегий буферизацииunitbuf; это флаг в std::ostream который вы можете установить или сбросить (std::ios_base::set() а также std::ios_base::unset()& # X2014;std::ios_base это базовый класс std::ostream, так что вы можете вызвать эти функции наstd::ostream объект). когдаunitbuf установлен,std::ostream добавляет вызовflush() до конца каждой функции вывода, поэтому, когда вы пишете:

std::cerr << "hello, world";

поток будет смыт послеall символов в строке выводятся при условииunitbuf установлено. На старте,unitbuf установлено заstd::cerr; по умолчанию он не установлен ни для одного другого файла. Но ты Вы можете установить или сбросить его, как вы хотите. Я бы рекомендовал против сбросив егоstd::cerr, но еслиstd::cout выводит на интерактивное устройство, имеет смысл установить его там.

Обратите внимание, что все, о чем здесь идет речь, это буфер вstreambuf. Typically, the OS also buffers. All flushing the buffer does is transfer the characters to the OS; this fact means that you cannot use ofstream непосредственно, когда требуется целостность транзакции.

3) Когда вы вводите строку или символьный буфер, используя>>, std::istream сначала пропускает начальные пробелы, а затем вводит до но не включая следующий пробел. В формальном плане стандарт, это "выдержки" символы из потока, так что они больше не будет виден (если вы не ищете, если поток поддерживает это). Следующий вход будет срабатывать там, где остановился предыдущий. Будь то следующие символы находятся в буфере или все еще на диске, на самом деле не имеет значения.

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

Так же, какstd::ostream используетstreambuf для вывода, std::istream использует один, чтобы получить каждого отдельного персонажа. В этом случае изstd::cinобычно это будетfilebuf; когдаistream просит персонажа,filebuf вернет один из своего буфера, если у него есть один; если это не так, он будет пытаться заполнить буфер, например, запрос 512 (или независимо от его размера буфера) символов из ОПЕРАЦИОННЫЕ СИСТЕМЫ. Который будет отвечать в соответствии с его политикой буферизации для устройство, как описано выше.

Во всяком случае, еслиstd::cin подключен к клавиатуре, и вы набранный"hello world"все введенные вами символы будут прочитаны в конце концов (Но если вы используете>>там будет много из пробелов, которыеyou не вижу.)

0

so to avoid doing slow things often the data is stored in memory until either a certain amount of data has been entered or the buffer is flushed manually with fflush or std::endl. The result of this is sometimes that text might not be written to the terminal at the moment you expect it to.

Since the timing of error messages is more critical than normal output, the performance hit is ignored and the data is not buffered. However, since a string is passed in a single piece of data, it is written in one call (inside a loop somewhere).

It world would still be in the buffer, but it's quite easy to prove this yourself by trying it in a 3 line program. However, your example will fail since you are attempting to write into unallocated memory. You should be taking input into a std::string instead.

Error: User Rate Limit ExceededfilebufError: User Rate Limit Exceededstd::cerrError: User Rate Limit ExceededunitbufError: User Rate Limit ExceededostreamError: User Rate Limit Exceeded>>Error: User Rate Limit Exceeded
Error: User Rate Limit ExceededunitbufError: User Rate Limit Exceeded
Error: User Rate Limit Exceeded AlexDan
2

то есть файловый и консольный ввод-вывод очень медленный по сравнению с операциями с памятью.

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

Это очень важно для потоков, потому что

std::cout << 1 << "hello" << ' ' << "world\n";

Было бы 4 записи в файл, который неэффективен.

Однако, в случае с std :: cout, cin и cerr, для этих типов по умолчанию буферизация отключена, чтобы гарантировать, что она может использоваться совместно с std :: printf и std ::puts и т.

Чтобы снова включить его (что я рекомендую сделать):

std::ios_base::sync_with_stdio(false);

Но не используйте вывод консоли в стиле C, пока он установлен в ложь, иначе могут произойти плохие вещи.

Error: User Rate Limit Exceeded
Error: User Rate Limit ExceededclogError: User Rate Limit ExceededcerrError: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded AlexDan
1

При буферизованном выводе существует область памяти, называемая буфером, в которой записываемый материал сохраняется до того, как он фактически записывается в вывод. Когда ты сказалcout << "hi" строка, вероятно, только копируется в этот буфер и не записывается. Cout обычно ждет, пока эта память не будет заполнена, прежде чем она действительно начнет писать вещи.

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

2) it said in my book that everything sent to cerr is written to the standard error device immediatly, does this mean it send 'h' and then 'i'...?

Это просто означает, что буфер не используется. cerr может по-прежнему отправлять «h»; и & amp ;, i; i '; в то же время, поскольку он уже имеет их обоих.

3)in this example ch will be assigned to "hello" and "world" will be ignored does it mean that it still in the buffer and it will affect the results of future statements ?

Это не имеет ничего общего с буферизацией. оператор & gt; & gt; для char * определено чтение до тех пор, пока он не увидит пробел, поэтому он останавливается на промежутке между & quot; привет ' и "мир". Но да, в следующий раз, когда вы будете читать, вы получите «мир».

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

std::string s;
cin >> s;

)

2

жения.

#include <iostream>
int main() {
    std::cout<<"Start";
    //std::cout<<"Start"<<std::endl; // line buffered, endl will flush.
    double j = 2;
    for(int i = 0; i < 100000000; i++){
        j = i / (i+1);
    }
    std::cout<<j;
    return 0;
}

Попробуйте разницу между двумя "Старт" рейтинги, затем измените на cerr. Разница, которую вы заметили, связана с буферизацией.

Формулировка занимает на моей установке около 2 секунд. Возможно, вам придется настроить i & lt; состояние на ваше.

Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded AlexDan
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded

Похожие вопросы