Я знаю, что это будет довольно глупый вопрос, но, прочитав так много документов о всей «буферной» системе, я не могу понять, почему люди сбрасывают поток, а не буфер.
Я видел людей, пишущих такие вещи:
FILE* file=fopen("mytext.txt","wr");
char buffer[10]="";
setbuf(file,buffer);
//do some stuff....
fflush(file);
....
fclose(file);
Поэтому мне интересно, так как мы на самом деле храним вещи в буфере, почему мы очищаем поток, с которым он связан, а не очищаем буфер напрямую, которые на самом деле хранят что-то и должны быть сброшены.(ну, некоторые люди говорят мне, что если все пойдет так, как я сказал, это будет то же самое, что беспокоит меня …)
Например, мы не можем писать такие вещи, какfflush(buffer)
.Зачем?
Flushing копирует данные из внутреннего буфера потока в базовый файл.
Таким образом, функция сброса должна знать источник и место назначения для копирования.
Это зависит от реализации ввода / вывода, для C ++ <iostream>
увидеть ответ Джерри Коффин — буферы в <iostream>
умнее
В стиле C <cstdio>
, если вы хотите сбросить только с одним аргументом, либо FILE*
или массив char должен знать о файле, в который он должен копироваться.
Ваш буфер — это тупой массив, он просто хранит данные для чтения / записи. Так как там нет никакой дополнительной информации, функция, которая получает указатель на буфер, не может знать место назначения, куда его записать — поэтому мнимая fflush
вызов будет выглядеть fflush(buffer, file);
который никуда тебя не приведет. С другой стороны, FILE*
сохраняет указатель на ваш буфер (вы устанавливаете указатель с помощью setbuf(file,buffer)
вызов функции).
Следующее касается только iostreams и их буферных объектов. Информацию о буферах, связанных с вводом / выводом в стиле C, см. В ответе @ milleniumbug.
Главным образом потому, что вы (по крайней мере, обычно) хотите установить битовый бит потока, если попытка очистки основного буфера не удалась.
Есть также немного сложный маленький танец, который потоки используют при взаимодействии с нижележащим потоком, когда поток создает часовой объект, затем выполняет действие, а затем часовой объект уничтожается. Часовой предназначен для обеспечения безопасности операций с префиксами и суффиксами.
Таким образом, общая последовательность выглядит примерно так:
create sentry
if that succeeds (sentry converts to true) call rdbuf()->pubsync()
if that fails (returns -1) setstate(badbit);
Потоковый буфер (например, basic_filebuf
) непосредственно присоединяется к базовому объекту файловой системы — фактически все взаимодействие между объектом iostream и базовым файловым объектом выполняется с помощью файловый буфер. Как показано выше, когда объект потока должен очистить буфер, все, что ему нужно сделать, это сказать буферу сбросить себя, вызвав буфер pubsync()
функция-член.
basic_ostream& промывать();
Эффекты: ведет себя как неформатированная выходная функция (как описано в пункте 27.7.3.6.1). Если rdbuf () не является нулевым указателем, создает объект sentry. Если этот объект возвращает true при преобразовании в значение типа bool, функция вызывает rdbuf () -> pubsync (). Если эта функция возвращает -1, то вызывает setstate (badbit) (который может выдать ios_base :: fail (27.5.5.4)). В противном случае, если объект sentry возвращает false, ничего не происходит.
Возвращает: * это.
…и [ofstream.cons] / 2:
явный basic_ofstream (const char * s,
ios_base :: openmode mode = ios_base :: out);Эффекты: Создает объект класса basic_ofstream, инициализируя базовый класс с помощью basic_ostream (&sb) и инициализирует sb с помощью basic_filebuf ()) (27.7.3.2, 27.9.1.2), затем вызывает rdbuf () -> open (s, mode | ios_base :: out). Если эта функция возвращает нулевой указатель, вызывается setstate (failbit).
Я не могу понять, почему люди сбрасывают поток, а не буфер.
Поскольку буфер не знает, куда он должен быть сброшен. Поток делает.
FILE* file=fopen("mytext.txt","wr"); setbuf(file,buffer);
По умолчанию FILE
Структура содержит указатель на собственный внутренний буфер. setbuf()
заменяет этот буфер на тот, который предоставляет вызывающая сторона. Но в любом случае, fwrite()
, fput...()
и другие подобные функции записывают данные в текущий буфер потока, и fflush()
сбрасывает содержимое этого буфера в основной файл.
КСТАТИ, setbuf()
требует, чтобы предоставленный вызывающим буфер был как минимум BUFSIZ
в размере:
char buffer[BUFSIZ]="";
Поэтому мне интересно, так как мы на самом деле храним вещи в буфере, почему мы сбрасываем поток, с которым он связан, а не очищаем буфер напрямую, который на самом деле что-то хранит и должен быть очищен.
Потому что буфер — это просто хранилище данных. Он ничего не знает о том, как используются данные. Поток знает, для чего используется его буфер (кэшировать записанные данные) и куда его нужно сбрасывать (связанный файл). Поэтому вы должны очистить поток, чтобы он мог использовать эту информацию.
Например, мы не можем писать такие вещи, как fflush (буфер). Зачем?
И где вы ожидаете, что буфер очистит свой контент? У него нет такой информации.